diff --git a/Packages/NB_FX/.git.backup/COMMITMESSAGE b/Packages/NB_FX/.git.backup/COMMITMESSAGE new file mode 100644 index 00000000..229ed97b --- /dev/null +++ b/Packages/NB_FX/.git.backup/COMMITMESSAGE @@ -0,0 +1 @@ +VersionCompatitive \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/COMMIT_EDITMSG b/Packages/NB_FX/.git.backup/COMMIT_EDITMSG new file mode 100644 index 00000000..4967cf2a --- /dev/null +++ b/Packages/NB_FX/.git.backup/COMMIT_EDITMSG @@ -0,0 +1 @@ +chore: normalize NBShader2 HLSL line endings diff --git a/Packages/NB_FX/.git.backup/FETCH_HEAD b/Packages/NB_FX/.git.backup/FETCH_HEAD new file mode 100644 index 00000000..fcf005b3 --- /dev/null +++ b/Packages/NB_FX/.git.backup/FETCH_HEAD @@ -0,0 +1,4 @@ +ee26c55dc0b55a14d06d3840a49da6c829246082 branch 'master' of https://github.com/xuanshushu/NB_FX +fa41b19c57420d8a51db2afeb96c3cc34ee6c440 not-for-merge branch 'Dev/HDRP' of https://github.com/xuanshushu/NB_FX +c99774e37f3796362ab73a04621ca058fab49b3a not-for-merge branch 'feature/nbshader-2' of https://github.com/xuanshushu/NB_FX +038d9f01f9ca65ec35655c8d75dabc2a6dbc7586 not-for-merge branch 'feature/vat' of https://github.com/xuanshushu/NB_FX diff --git a/Packages/NB_FX/.git.backup/HEAD b/Packages/NB_FX/.git.backup/HEAD new file mode 100644 index 00000000..cb089cd8 --- /dev/null +++ b/Packages/NB_FX/.git.backup/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/Packages/NB_FX/.git.backup/ORIG_HEAD b/Packages/NB_FX/.git.backup/ORIG_HEAD new file mode 100644 index 00000000..c1e450d6 --- /dev/null +++ b/Packages/NB_FX/.git.backup/ORIG_HEAD @@ -0,0 +1 @@ +458adc6c21482a7c73c14bb80e0340b6c9144e57 diff --git a/Packages/NB_FX/.git.backup/config b/Packages/NB_FX/.git.backup/config new file mode 100644 index 00000000..3fc844ce --- /dev/null +++ b/Packages/NB_FX/.git.backup/config @@ -0,0 +1,23 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true +[submodule] + active = . +[remote "origin"] + url = https://github.com/xuanshushu/NB_FX.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "master"] + remote = origin + merge = refs/heads/master +[lfs] + repositoryformatversion = 0 +[branch "feature/nbshader-2"] + remote = origin + merge = refs/heads/feature/nbshader-2 + vscode-merge-base = origin/feature/nbshader-2 +[lfs "https://github.com/xuanshushu/NB_FX.git/info/lfs"] + access = basic diff --git a/Packages/NB_FX/.git.backup/description b/Packages/NB_FX/.git.backup/description new file mode 100644 index 00000000..498b267a --- /dev/null +++ b/Packages/NB_FX/.git.backup/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/Packages/NB_FX/.git.backup/fork-settings b/Packages/NB_FX/.git.backup/fork-settings new file mode 100644 index 00000000..25508dee --- /dev/null +++ b/Packages/NB_FX/.git.backup/fork-settings @@ -0,0 +1 @@ +{"draftMessage":"","recentNewBranchPrefix":null,"recentSearchQueries":[],"issuesRecentSearchQueries":[],"pullRequestsRecentSearchQueries":[],"pullRequestsDefaultRemote":null,"issuesDefaultRemote":null,"starredReferences":[],"filterReferences":[],"hiddenReferences":[],"signOff":false,"expandedSidebarItems":[{"title":"Branches","children":[{"title":"feature","children":[]}]},{"title":"Remotes","children":[{"title":"origin","children":[{"title":"feature","children":[]}]}]},{"title":"Stashes","children":[]}],"showBugtrackerLinks":true,"trustSharedCommands":false,"hideTags":false,"collapseAllMergeRevisions":false,"collapseToggledShas":[],"hideStashesInRevisionList":false,"recentRemote":null,"pushLastCustomRefspec":null,"leanBranchingMainBranch":null,"leanBranchingNoFastForward":false,"tabWidth":4,"hideUntrackedFiles":false,"gitignoreSuggestionDismissed":false} \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/hooks/applypatch-msg.sample b/Packages/NB_FX/.git.backup/hooks/applypatch-msg.sample new file mode 100644 index 00000000..a5d7b84a --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/Packages/NB_FX/.git.backup/hooks/commit-msg.sample b/Packages/NB_FX/.git.backup/hooks/commit-msg.sample new file mode 100644 index 00000000..b58d1184 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/Packages/NB_FX/.git.backup/hooks/fsmonitor-watchman.sample b/Packages/NB_FX/.git.backup/hooks/fsmonitor-watchman.sample new file mode 100644 index 00000000..23e856f5 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/Packages/NB_FX/.git.backup/hooks/post-checkout b/Packages/NB_FX/.git.backup/hooks/post-checkout new file mode 100644 index 00000000..c37815e2 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/post-checkout @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-checkout'.\n"; exit 2; } +git lfs post-checkout "$@" diff --git a/Packages/NB_FX/.git.backup/hooks/post-commit b/Packages/NB_FX/.git.backup/hooks/post-commit new file mode 100644 index 00000000..e5230c30 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/post-commit @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-commit'.\n"; exit 2; } +git lfs post-commit "$@" diff --git a/Packages/NB_FX/.git.backup/hooks/post-merge b/Packages/NB_FX/.git.backup/hooks/post-merge new file mode 100644 index 00000000..c99b752a --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/post-merge @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-merge'.\n"; exit 2; } +git lfs post-merge "$@" diff --git a/Packages/NB_FX/.git.backup/hooks/post-update.sample b/Packages/NB_FX/.git.backup/hooks/post-update.sample new file mode 100644 index 00000000..ec17ec19 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/Packages/NB_FX/.git.backup/hooks/pre-applypatch.sample b/Packages/NB_FX/.git.backup/hooks/pre-applypatch.sample new file mode 100644 index 00000000..4142082b --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/Packages/NB_FX/.git.backup/hooks/pre-commit.sample b/Packages/NB_FX/.git.backup/hooks/pre-commit.sample new file mode 100644 index 00000000..29ed5ee4 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff-index --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/Packages/NB_FX/.git.backup/hooks/pre-merge-commit.sample b/Packages/NB_FX/.git.backup/hooks/pre-merge-commit.sample new file mode 100644 index 00000000..399eab19 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/Packages/NB_FX/.git.backup/hooks/pre-push b/Packages/NB_FX/.git.backup/hooks/pre-push new file mode 100644 index 00000000..216e9152 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/pre-push @@ -0,0 +1,3 @@ +#!/bin/sh +command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/pre-push'.\n"; exit 2; } +git lfs pre-push "$@" diff --git a/Packages/NB_FX/.git.backup/hooks/pre-push.sample b/Packages/NB_FX/.git.backup/hooks/pre-push.sample new file mode 100644 index 00000000..4ce688d3 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/Packages/NB_FX/.git.backup/hooks/pre-rebase.sample b/Packages/NB_FX/.git.backup/hooks/pre-rebase.sample new file mode 100644 index 00000000..6cbef5c3 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/Packages/NB_FX/.git.backup/hooks/pre-receive.sample b/Packages/NB_FX/.git.backup/hooks/pre-receive.sample new file mode 100644 index 00000000..a1fd29ec --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/Packages/NB_FX/.git.backup/hooks/prepare-commit-msg.sample b/Packages/NB_FX/.git.backup/hooks/prepare-commit-msg.sample new file mode 100644 index 00000000..10fa14c5 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/Packages/NB_FX/.git.backup/hooks/push-to-checkout.sample b/Packages/NB_FX/.git.backup/hooks/push-to-checkout.sample new file mode 100644 index 00000000..af5a0c00 --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/Packages/NB_FX/.git.backup/hooks/update.sample b/Packages/NB_FX/.git.backup/hooks/update.sample new file mode 100644 index 00000000..c4d426bc --- /dev/null +++ b/Packages/NB_FX/.git.backup/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/Packages/NB_FX/.git.backup/index b/Packages/NB_FX/.git.backup/index new file mode 100644 index 00000000..0e818cd1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/index differ diff --git a/Packages/NB_FX/.git.backup/info/exclude b/Packages/NB_FX/.git.backup/info/exclude new file mode 100644 index 00000000..a5196d1b --- /dev/null +++ b/Packages/NB_FX/.git.backup/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/Packages/NB_FX/.git.backup/lfs/cache/locks/refs/heads/feature/nbshader-2/verifiable b/Packages/NB_FX/.git.backup/lfs/cache/locks/refs/heads/feature/nbshader-2/verifiable new file mode 100644 index 00000000..a6476075 --- /dev/null +++ b/Packages/NB_FX/.git.backup/lfs/cache/locks/refs/heads/feature/nbshader-2/verifiable @@ -0,0 +1 @@ +{"ours":[],"theirs":[]} diff --git a/Packages/NB_FX/.git.backup/lfs/cache/locks/refs/heads/master/verifiable b/Packages/NB_FX/.git.backup/lfs/cache/locks/refs/heads/master/verifiable new file mode 100644 index 00000000..a6476075 --- /dev/null +++ b/Packages/NB_FX/.git.backup/lfs/cache/locks/refs/heads/master/verifiable @@ -0,0 +1 @@ +{"ours":[],"theirs":[]} diff --git a/Packages/NB_FX/.git.backup/objects/00/225691959687f6ec6cf5a64bcd1ee8be29f8a3 b/Packages/NB_FX/.git.backup/objects/00/225691959687f6ec6cf5a64bcd1ee8be29f8a3 new file mode 100644 index 00000000..377b1b88 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/00/225691959687f6ec6cf5a64bcd1ee8be29f8a3 differ diff --git a/Packages/NB_FX/.git.backup/objects/00/62a7617aaf850c4d588b9b6a60fc951b21cdec b/Packages/NB_FX/.git.backup/objects/00/62a7617aaf850c4d588b9b6a60fc951b21cdec new file mode 100644 index 00000000..ca5666f4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/00/62a7617aaf850c4d588b9b6a60fc951b21cdec differ diff --git a/Packages/NB_FX/.git.backup/objects/00/9ce529541d1808fe598c6bdfa540db0f32cd5d b/Packages/NB_FX/.git.backup/objects/00/9ce529541d1808fe598c6bdfa540db0f32cd5d new file mode 100644 index 00000000..eac7f85c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/00/9ce529541d1808fe598c6bdfa540db0f32cd5d differ diff --git a/Packages/NB_FX/.git.backup/objects/01/a923f3824943de8508403a3a9bb3d916c4694a b/Packages/NB_FX/.git.backup/objects/01/a923f3824943de8508403a3a9bb3d916c4694a new file mode 100644 index 00000000..cb6ae408 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/01/a923f3824943de8508403a3a9bb3d916c4694a differ diff --git a/Packages/NB_FX/.git.backup/objects/01/add826defbfee2d74d0a1ba2f4b17602d93d98 b/Packages/NB_FX/.git.backup/objects/01/add826defbfee2d74d0a1ba2f4b17602d93d98 new file mode 100644 index 00000000..fb0a26c2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/01/add826defbfee2d74d0a1ba2f4b17602d93d98 differ diff --git a/Packages/NB_FX/.git.backup/objects/01/d74c38aa39f716f950a3f04b1990c33b0c75ad b/Packages/NB_FX/.git.backup/objects/01/d74c38aa39f716f950a3f04b1990c33b0c75ad new file mode 100644 index 00000000..660ac0eb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/01/d74c38aa39f716f950a3f04b1990c33b0c75ad differ diff --git a/Packages/NB_FX/.git.backup/objects/01/dcfc1c30a19fc6a80d8c2ce7c57cec7f8aac84 b/Packages/NB_FX/.git.backup/objects/01/dcfc1c30a19fc6a80d8c2ce7c57cec7f8aac84 new file mode 100644 index 00000000..d7e35c32 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/01/dcfc1c30a19fc6a80d8c2ce7c57cec7f8aac84 differ diff --git a/Packages/NB_FX/.git.backup/objects/02/532c11d86252a750532b0022040a5ff69c6ffd b/Packages/NB_FX/.git.backup/objects/02/532c11d86252a750532b0022040a5ff69c6ffd new file mode 100644 index 00000000..113f924b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/02/532c11d86252a750532b0022040a5ff69c6ffd differ diff --git a/Packages/NB_FX/.git.backup/objects/02/7c8e40a1c70857f70c54b6e51b797522af4644 b/Packages/NB_FX/.git.backup/objects/02/7c8e40a1c70857f70c54b6e51b797522af4644 new file mode 100644 index 00000000..7e06e2e1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/02/7c8e40a1c70857f70c54b6e51b797522af4644 differ diff --git a/Packages/NB_FX/.git.backup/objects/02/95f39337f1cee12e6259b509d34e4f30e3d8b9 b/Packages/NB_FX/.git.backup/objects/02/95f39337f1cee12e6259b509d34e4f30e3d8b9 new file mode 100644 index 00000000..dc3a05aa Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/02/95f39337f1cee12e6259b509d34e4f30e3d8b9 differ diff --git a/Packages/NB_FX/.git.backup/objects/02/f62e494b349a24776e986bb75b63e5a6a21c00 b/Packages/NB_FX/.git.backup/objects/02/f62e494b349a24776e986bb75b63e5a6a21c00 new file mode 100644 index 00000000..7cd0306b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/02/f62e494b349a24776e986bb75b63e5a6a21c00 differ diff --git a/Packages/NB_FX/.git.backup/objects/02/fce045832c43d0de9791c02ff02290d63bddb5 b/Packages/NB_FX/.git.backup/objects/02/fce045832c43d0de9791c02ff02290d63bddb5 new file mode 100644 index 00000000..a0ae06b9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/02/fce045832c43d0de9791c02ff02290d63bddb5 differ diff --git a/Packages/NB_FX/.git.backup/objects/03/14c94bb8c7c454dcc9ea698946a9cb6dc1540e b/Packages/NB_FX/.git.backup/objects/03/14c94bb8c7c454dcc9ea698946a9cb6dc1540e new file mode 100644 index 00000000..baebea1c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/03/14c94bb8c7c454dcc9ea698946a9cb6dc1540e differ diff --git a/Packages/NB_FX/.git.backup/objects/03/84d8c8518fbd6382f00e5024bc974611ebebf8 b/Packages/NB_FX/.git.backup/objects/03/84d8c8518fbd6382f00e5024bc974611ebebf8 new file mode 100644 index 00000000..72c95be8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/03/84d8c8518fbd6382f00e5024bc974611ebebf8 differ diff --git a/Packages/NB_FX/.git.backup/objects/03/a9e802bc41557417463b9c0ef46495453ae2fd b/Packages/NB_FX/.git.backup/objects/03/a9e802bc41557417463b9c0ef46495453ae2fd new file mode 100644 index 00000000..1a3f2daa Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/03/a9e802bc41557417463b9c0ef46495453ae2fd differ diff --git a/Packages/NB_FX/.git.backup/objects/03/d0c7f43698333cec1c8fe81bb3d6e1b0daeec9 b/Packages/NB_FX/.git.backup/objects/03/d0c7f43698333cec1c8fe81bb3d6e1b0daeec9 new file mode 100644 index 00000000..af2aeacf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/03/d0c7f43698333cec1c8fe81bb3d6e1b0daeec9 differ diff --git a/Packages/NB_FX/.git.backup/objects/03/e9773fc9825b04cdd390108f42a6ed354cb9a3 b/Packages/NB_FX/.git.backup/objects/03/e9773fc9825b04cdd390108f42a6ed354cb9a3 new file mode 100644 index 00000000..8fdd789d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/03/e9773fc9825b04cdd390108f42a6ed354cb9a3 differ diff --git a/Packages/NB_FX/.git.backup/objects/04/1b838b6cef3ba091038f5d26108de1e3b1bef7 b/Packages/NB_FX/.git.backup/objects/04/1b838b6cef3ba091038f5d26108de1e3b1bef7 new file mode 100644 index 00000000..c3c6cca5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/04/1b838b6cef3ba091038f5d26108de1e3b1bef7 differ diff --git a/Packages/NB_FX/.git.backup/objects/04/98c2f551676fdb5244cc0b78cc004c06759184 b/Packages/NB_FX/.git.backup/objects/04/98c2f551676fdb5244cc0b78cc004c06759184 new file mode 100644 index 00000000..4b0f091a --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/04/98c2f551676fdb5244cc0b78cc004c06759184 @@ -0,0 +1,2 @@ +x]j1E]W'8M41pRFF+= 3ʸùDŽdHoSOQ.;Mho7l1/j͸f)rE~N +[۟Ђ9_"[-.mUBNى¼]nKa'h62̥n[t< Yb?TP \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/04/c172d0b25034b228de03ecf9935781c240323e b/Packages/NB_FX/.git.backup/objects/04/c172d0b25034b228de03ecf9935781c240323e new file mode 100644 index 00000000..bd02451f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/04/c172d0b25034b228de03ecf9935781c240323e differ diff --git a/Packages/NB_FX/.git.backup/objects/05/1bd166e97459abea3597343ed66b7583e45307 b/Packages/NB_FX/.git.backup/objects/05/1bd166e97459abea3597343ed66b7583e45307 new file mode 100644 index 00000000..f1e34d99 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/05/1bd166e97459abea3597343ed66b7583e45307 differ diff --git a/Packages/NB_FX/.git.backup/objects/05/b0fdfa00844fef32769d7d5921f1882f762e6b b/Packages/NB_FX/.git.backup/objects/05/b0fdfa00844fef32769d7d5921f1882f762e6b new file mode 100644 index 00000000..e38d2a8a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/05/b0fdfa00844fef32769d7d5921f1882f762e6b differ diff --git a/Packages/NB_FX/.git.backup/objects/05/e19b90970f1d21e13bed1a94bf268a3e53613c b/Packages/NB_FX/.git.backup/objects/05/e19b90970f1d21e13bed1a94bf268a3e53613c new file mode 100644 index 00000000..adc9f3da Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/05/e19b90970f1d21e13bed1a94bf268a3e53613c differ diff --git a/Packages/NB_FX/.git.backup/objects/06/38e6dcfc5d633ec530c1bf8ba4945c31d2af61 b/Packages/NB_FX/.git.backup/objects/06/38e6dcfc5d633ec530c1bf8ba4945c31d2af61 new file mode 100644 index 00000000..e4ac359f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/06/38e6dcfc5d633ec530c1bf8ba4945c31d2af61 differ diff --git a/Packages/NB_FX/.git.backup/objects/07/8ee001b278fbdc1406a9d9eb7b544efb0599c9 b/Packages/NB_FX/.git.backup/objects/07/8ee001b278fbdc1406a9d9eb7b544efb0599c9 new file mode 100644 index 00000000..b3892d99 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/07/8ee001b278fbdc1406a9d9eb7b544efb0599c9 differ diff --git a/Packages/NB_FX/.git.backup/objects/08/ad82ca638a5e35b5aba6520ecd7dfa2e0a1588 b/Packages/NB_FX/.git.backup/objects/08/ad82ca638a5e35b5aba6520ecd7dfa2e0a1588 new file mode 100644 index 00000000..d9c0c24c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/08/ad82ca638a5e35b5aba6520ecd7dfa2e0a1588 differ diff --git a/Packages/NB_FX/.git.backup/objects/08/fd2166946f2a427b8527826e120bee66f6dab5 b/Packages/NB_FX/.git.backup/objects/08/fd2166946f2a427b8527826e120bee66f6dab5 new file mode 100644 index 00000000..94237acf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/08/fd2166946f2a427b8527826e120bee66f6dab5 differ diff --git a/Packages/NB_FX/.git.backup/objects/09/2e1ced62c0c64df3f0250131b61064dc95db67 b/Packages/NB_FX/.git.backup/objects/09/2e1ced62c0c64df3f0250131b61064dc95db67 new file mode 100644 index 00000000..052eeff8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/09/2e1ced62c0c64df3f0250131b61064dc95db67 differ diff --git a/Packages/NB_FX/.git.backup/objects/09/7246e13f791557885430a470c85767d200cce2 b/Packages/NB_FX/.git.backup/objects/09/7246e13f791557885430a470c85767d200cce2 new file mode 100644 index 00000000..9a08bc8d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/09/7246e13f791557885430a470c85767d200cce2 differ diff --git a/Packages/NB_FX/.git.backup/objects/09/866e190d5ea06c6263214f0c914075279d1272 b/Packages/NB_FX/.git.backup/objects/09/866e190d5ea06c6263214f0c914075279d1272 new file mode 100644 index 00000000..ee489e32 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/09/866e190d5ea06c6263214f0c914075279d1272 @@ -0,0 +1,2 @@ +xAn s+涇(``h lb,%}iUy_[қ*J9q28Of\PQ\yKӭ9URM)4H^<g~" +KaCȹ"g$g_Sc930L_{+8+24q뿋ӷd \V9n[ߡǖEy\ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/09/ac629eb82ebf28cd8d5b3df4457bad5dbda9b4 b/Packages/NB_FX/.git.backup/objects/09/ac629eb82ebf28cd8d5b3df4457bad5dbda9b4 new file mode 100644 index 00000000..8cd4b289 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/09/ac629eb82ebf28cd8d5b3df4457bad5dbda9b4 differ diff --git a/Packages/NB_FX/.git.backup/objects/0a/16ff0cfaafd7c7f229c9e38dd19a1a344615ea b/Packages/NB_FX/.git.backup/objects/0a/16ff0cfaafd7c7f229c9e38dd19a1a344615ea new file mode 100644 index 00000000..e876a3f4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0a/16ff0cfaafd7c7f229c9e38dd19a1a344615ea differ diff --git a/Packages/NB_FX/.git.backup/objects/0a/7fb9ed3de3f0dc131107f6f0ba801b3008ec5d b/Packages/NB_FX/.git.backup/objects/0a/7fb9ed3de3f0dc131107f6f0ba801b3008ec5d new file mode 100644 index 00000000..743d0e5f --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/0a/7fb9ed3de3f0dc131107f6f0ba801b3008ec5d @@ -0,0 +1,2 @@ +x]M +0@a=RDFBf)i"fOa.wL3q+hGFǡ6reM}'n^4Ǯau!ⲡiNĪw 7ZRT͑ )7ӿ}*77 \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/0a/91ce132eac8959a6f31c66e08e62c36c4c6c73 b/Packages/NB_FX/.git.backup/objects/0a/91ce132eac8959a6f31c66e08e62c36c4c6c73 new file mode 100644 index 00000000..25b47a3b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0a/91ce132eac8959a6f31c66e08e62c36c4c6c73 differ diff --git a/Packages/NB_FX/.git.backup/objects/0a/effa0c968a61ce84ada33a0f42c6c519af7ff1 b/Packages/NB_FX/.git.backup/objects/0a/effa0c968a61ce84ada33a0f42c6c519af7ff1 new file mode 100644 index 00000000..fcb5cd2e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0a/effa0c968a61ce84ada33a0f42c6c519af7ff1 differ diff --git a/Packages/NB_FX/.git.backup/objects/0b/35560146b2d1f52e331614c70824a51e2594b6 b/Packages/NB_FX/.git.backup/objects/0b/35560146b2d1f52e331614c70824a51e2594b6 new file mode 100644 index 00000000..e4d36924 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0b/35560146b2d1f52e331614c70824a51e2594b6 differ diff --git a/Packages/NB_FX/.git.backup/objects/0b/80111ec85fa75392d4526478275eb3e36dd6c0 b/Packages/NB_FX/.git.backup/objects/0b/80111ec85fa75392d4526478275eb3e36dd6c0 new file mode 100644 index 00000000..a4ad73b4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0b/80111ec85fa75392d4526478275eb3e36dd6c0 differ diff --git a/Packages/NB_FX/.git.backup/objects/0d/19f3c2dff135822d1e826e4757cde0dcbe4320 b/Packages/NB_FX/.git.backup/objects/0d/19f3c2dff135822d1e826e4757cde0dcbe4320 new file mode 100644 index 00000000..869d9339 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0d/19f3c2dff135822d1e826e4757cde0dcbe4320 differ diff --git a/Packages/NB_FX/.git.backup/objects/0d/1a9f389bf06acb4b97724da1d30c24f2bffc42 b/Packages/NB_FX/.git.backup/objects/0d/1a9f389bf06acb4b97724da1d30c24f2bffc42 new file mode 100644 index 00000000..dd631772 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0d/1a9f389bf06acb4b97724da1d30c24f2bffc42 differ diff --git a/Packages/NB_FX/.git.backup/objects/0d/8e1ea7efb89f6eb17600dee5b07dc8757eef80 b/Packages/NB_FX/.git.backup/objects/0d/8e1ea7efb89f6eb17600dee5b07dc8757eef80 new file mode 100644 index 00000000..e8f2bf69 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0d/8e1ea7efb89f6eb17600dee5b07dc8757eef80 differ diff --git a/Packages/NB_FX/.git.backup/objects/0d/abc5dc495b654587d2e65aca416054e8b9126c b/Packages/NB_FX/.git.backup/objects/0d/abc5dc495b654587d2e65aca416054e8b9126c new file mode 100644 index 00000000..374cc744 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0d/abc5dc495b654587d2e65aca416054e8b9126c differ diff --git a/Packages/NB_FX/.git.backup/objects/0f/1eb3dca18f728383ea77193ce18a1ad46bfc26 b/Packages/NB_FX/.git.backup/objects/0f/1eb3dca18f728383ea77193ce18a1ad46bfc26 new file mode 100644 index 00000000..7c126428 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0f/1eb3dca18f728383ea77193ce18a1ad46bfc26 differ diff --git a/Packages/NB_FX/.git.backup/objects/0f/4f05df83a425f7705dbaef9d1e979637b8de09 b/Packages/NB_FX/.git.backup/objects/0f/4f05df83a425f7705dbaef9d1e979637b8de09 new file mode 100644 index 00000000..fc4d4ded Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0f/4f05df83a425f7705dbaef9d1e979637b8de09 differ diff --git a/Packages/NB_FX/.git.backup/objects/0f/61f9df7e346650ce8e9a36109393e1f49632c0 b/Packages/NB_FX/.git.backup/objects/0f/61f9df7e346650ce8e9a36109393e1f49632c0 new file mode 100644 index 00000000..d70e490f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/0f/61f9df7e346650ce8e9a36109393e1f49632c0 differ diff --git a/Packages/NB_FX/.git.backup/objects/0f/f39b042ee6c85be9510233cab57d1b6d76c9f2 b/Packages/NB_FX/.git.backup/objects/0f/f39b042ee6c85be9510233cab57d1b6d76c9f2 new file mode 100644 index 00000000..139f75d5 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/0f/f39b042ee6c85be9510233cab57d1b6d76c9f2 @@ -0,0 +1,2 @@ +xN1 +0Wx/}(kn 鐤I.}TQ !$PᑵbNsAX%D༠eȘuNȶv! 5Dcj"^i|k>5`L(y450}4EUI˽,TBo}~?D \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/10/19e5bb6adaab2c107f172bd73d802a014e0732 b/Packages/NB_FX/.git.backup/objects/10/19e5bb6adaab2c107f172bd73d802a014e0732 new file mode 100644 index 00000000..5f67e136 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/10/19e5bb6adaab2c107f172bd73d802a014e0732 differ diff --git a/Packages/NB_FX/.git.backup/objects/10/85774d5aa868a9363e644d0e61d35a27c82ed9 b/Packages/NB_FX/.git.backup/objects/10/85774d5aa868a9363e644d0e61d35a27c82ed9 new file mode 100644 index 00000000..73e34426 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/10/85774d5aa868a9363e644d0e61d35a27c82ed9 differ diff --git a/Packages/NB_FX/.git.backup/objects/10/ac40c6ba1628cc2cde1cec1a75dcd2155d58e5 b/Packages/NB_FX/.git.backup/objects/10/ac40c6ba1628cc2cde1cec1a75dcd2155d58e5 new file mode 100644 index 00000000..303f57ac Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/10/ac40c6ba1628cc2cde1cec1a75dcd2155d58e5 differ diff --git a/Packages/NB_FX/.git.backup/objects/10/fe7ea5e0f986c487bfdad82766e82d91c3ff9a b/Packages/NB_FX/.git.backup/objects/10/fe7ea5e0f986c487bfdad82766e82d91c3ff9a new file mode 100644 index 00000000..48f54792 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/10/fe7ea5e0f986c487bfdad82766e82d91c3ff9a differ diff --git a/Packages/NB_FX/.git.backup/objects/11/14dfd29651a8074f425650cc645ae045fa036e b/Packages/NB_FX/.git.backup/objects/11/14dfd29651a8074f425650cc645ae045fa036e new file mode 100644 index 00000000..234f3487 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/11/14dfd29651a8074f425650cc645ae045fa036e differ diff --git a/Packages/NB_FX/.git.backup/objects/11/d52ced18e87218be345531e078707cb98ff246 b/Packages/NB_FX/.git.backup/objects/11/d52ced18e87218be345531e078707cb98ff246 new file mode 100644 index 00000000..38418341 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/11/d52ced18e87218be345531e078707cb98ff246 differ diff --git a/Packages/NB_FX/.git.backup/objects/12/46568c62f217326666b53c25248f9d15dbd612 b/Packages/NB_FX/.git.backup/objects/12/46568c62f217326666b53c25248f9d15dbd612 new file mode 100644 index 00000000..bf26fd51 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/12/46568c62f217326666b53c25248f9d15dbd612 differ diff --git a/Packages/NB_FX/.git.backup/objects/12/96a5e24c4fdbb3ec2ca86c22ff444211d6fabb b/Packages/NB_FX/.git.backup/objects/12/96a5e24c4fdbb3ec2ca86c22ff444211d6fabb new file mode 100644 index 00000000..8fd04117 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/12/96a5e24c4fdbb3ec2ca86c22ff444211d6fabb differ diff --git a/Packages/NB_FX/.git.backup/objects/12/fbda0b2c926810bd22e3091511f5d947db57af b/Packages/NB_FX/.git.backup/objects/12/fbda0b2c926810bd22e3091511f5d947db57af new file mode 100644 index 00000000..27cfc77c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/12/fbda0b2c926810bd22e3091511f5d947db57af differ diff --git a/Packages/NB_FX/.git.backup/objects/13/0859995f08d112a90de8272f9197fad841d1f2 b/Packages/NB_FX/.git.backup/objects/13/0859995f08d112a90de8272f9197fad841d1f2 new file mode 100644 index 00000000..a6522da7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/13/0859995f08d112a90de8272f9197fad841d1f2 differ diff --git a/Packages/NB_FX/.git.backup/objects/13/3c29e8acce2f40cf78217572fb1dc8b816630e b/Packages/NB_FX/.git.backup/objects/13/3c29e8acce2f40cf78217572fb1dc8b816630e new file mode 100644 index 00000000..34b97b4a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/13/3c29e8acce2f40cf78217572fb1dc8b816630e differ diff --git a/Packages/NB_FX/.git.backup/objects/14/44958cef945db9a1e8b5d0848ddba2a53cac68 b/Packages/NB_FX/.git.backup/objects/14/44958cef945db9a1e8b5d0848ddba2a53cac68 new file mode 100644 index 00000000..d9c66728 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/14/44958cef945db9a1e8b5d0848ddba2a53cac68 differ diff --git a/Packages/NB_FX/.git.backup/objects/14/b82c80818e3b7d815f37e6ac8e495108647d3e b/Packages/NB_FX/.git.backup/objects/14/b82c80818e3b7d815f37e6ac8e495108647d3e new file mode 100644 index 00000000..d5421cd9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/14/b82c80818e3b7d815f37e6ac8e495108647d3e differ diff --git a/Packages/NB_FX/.git.backup/objects/14/d7e9526b61e59385a4d211193b7ef47360d2c0 b/Packages/NB_FX/.git.backup/objects/14/d7e9526b61e59385a4d211193b7ef47360d2c0 new file mode 100644 index 00000000..64ae8941 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/14/d7e9526b61e59385a4d211193b7ef47360d2c0 differ diff --git a/Packages/NB_FX/.git.backup/objects/15/24445fb761dbccbc6c503b7362ee3d53ed8d61 b/Packages/NB_FX/.git.backup/objects/15/24445fb761dbccbc6c503b7362ee3d53ed8d61 new file mode 100644 index 00000000..28000100 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/15/24445fb761dbccbc6c503b7362ee3d53ed8d61 differ diff --git a/Packages/NB_FX/.git.backup/objects/15/58511a36884024d8f3a0d57bd01f2f9903db42 b/Packages/NB_FX/.git.backup/objects/15/58511a36884024d8f3a0d57bd01f2f9903db42 new file mode 100644 index 00000000..36f34e92 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/15/58511a36884024d8f3a0d57bd01f2f9903db42 differ diff --git a/Packages/NB_FX/.git.backup/objects/15/5a44ba9e0ba5b1a535d0ff86de128d72e0eaf2 b/Packages/NB_FX/.git.backup/objects/15/5a44ba9e0ba5b1a535d0ff86de128d72e0eaf2 new file mode 100644 index 00000000..628b98fc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/15/5a44ba9e0ba5b1a535d0ff86de128d72e0eaf2 differ diff --git a/Packages/NB_FX/.git.backup/objects/15/68f978be239dda2c4d44165662bedec53637fa b/Packages/NB_FX/.git.backup/objects/15/68f978be239dda2c4d44165662bedec53637fa new file mode 100644 index 00000000..5139c344 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/15/68f978be239dda2c4d44165662bedec53637fa differ diff --git a/Packages/NB_FX/.git.backup/objects/15/9b3c40c494fc23d16a7e769ecb3e4c78d92248 b/Packages/NB_FX/.git.backup/objects/15/9b3c40c494fc23d16a7e769ecb3e4c78d92248 new file mode 100644 index 00000000..21afc0af Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/15/9b3c40c494fc23d16a7e769ecb3e4c78d92248 differ diff --git a/Packages/NB_FX/.git.backup/objects/15/b350a680a89c28e60ff05bf9abbf4927ae4e2d b/Packages/NB_FX/.git.backup/objects/15/b350a680a89c28e60ff05bf9abbf4927ae4e2d new file mode 100644 index 00000000..c2bef457 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/15/b350a680a89c28e60ff05bf9abbf4927ae4e2d differ diff --git a/Packages/NB_FX/.git.backup/objects/15/bf3f846e79a4eade197b9106b98af2e0d7c98c b/Packages/NB_FX/.git.backup/objects/15/bf3f846e79a4eade197b9106b98af2e0d7c98c new file mode 100644 index 00000000..968c47b0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/15/bf3f846e79a4eade197b9106b98af2e0d7c98c differ diff --git a/Packages/NB_FX/.git.backup/objects/15/ea7c715650c7a5c74177f9b4b5f6efae284b9c b/Packages/NB_FX/.git.backup/objects/15/ea7c715650c7a5c74177f9b4b5f6efae284b9c new file mode 100644 index 00000000..fdb814ab --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/15/ea7c715650c7a5c74177f9b4b5f6efae284b9c @@ -0,0 +1,2 @@ +xTn0 _F[Ҡ-mŰ6LjT InaPmU$%M>>>>iJ|82ضۈ: Zhvlu ـE'`{YiS݀tx)?Rm-JZ yB:f_3USrykRMl13F <) ?SvrwilL? 8" :QR4PEݱ~y'1FE=Jk%6U-"'gqT _F76pYRVl\{s5Ҹ۬>45yghZZI©`ʧ{$6)1)疉vŮ@ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/16/057d5bad7b84cf7605f7d00f42db02237000fd b/Packages/NB_FX/.git.backup/objects/16/057d5bad7b84cf7605f7d00f42db02237000fd new file mode 100644 index 00000000..f40b96df Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/16/057d5bad7b84cf7605f7d00f42db02237000fd differ diff --git a/Packages/NB_FX/.git.backup/objects/16/47030ddb785c20ea07ce022f19e69334d3f9f8 b/Packages/NB_FX/.git.backup/objects/16/47030ddb785c20ea07ce022f19e69334d3f9f8 new file mode 100644 index 00000000..5246d7a3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/16/47030ddb785c20ea07ce022f19e69334d3f9f8 differ diff --git a/Packages/NB_FX/.git.backup/objects/16/94aa14f15028722d9f6233ca2993869963ca32 b/Packages/NB_FX/.git.backup/objects/16/94aa14f15028722d9f6233ca2993869963ca32 new file mode 100644 index 00000000..84ed33cc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/16/94aa14f15028722d9f6233ca2993869963ca32 differ diff --git a/Packages/NB_FX/.git.backup/objects/16/ad49ccd907795aa4db8a9436f27e1f0edb2911 b/Packages/NB_FX/.git.backup/objects/16/ad49ccd907795aa4db8a9436f27e1f0edb2911 new file mode 100644 index 00000000..ab850d36 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/16/ad49ccd907795aa4db8a9436f27e1f0edb2911 differ diff --git a/Packages/NB_FX/.git.backup/objects/16/bcb8b1848765b93c4cf2fed6a678be9a4def98 b/Packages/NB_FX/.git.backup/objects/16/bcb8b1848765b93c4cf2fed6a678be9a4def98 new file mode 100644 index 00000000..ffc64701 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/16/bcb8b1848765b93c4cf2fed6a678be9a4def98 differ diff --git a/Packages/NB_FX/.git.backup/objects/16/c3db626e8c675ea2378693b8034413cd2a22ca b/Packages/NB_FX/.git.backup/objects/16/c3db626e8c675ea2378693b8034413cd2a22ca new file mode 100644 index 00000000..4add7f65 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/16/c3db626e8c675ea2378693b8034413cd2a22ca differ diff --git a/Packages/NB_FX/.git.backup/objects/17/27b638c9b1c50bcd40b19530048b159d0bbaf2 b/Packages/NB_FX/.git.backup/objects/17/27b638c9b1c50bcd40b19530048b159d0bbaf2 new file mode 100644 index 00000000..3ba2545c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/17/27b638c9b1c50bcd40b19530048b159d0bbaf2 differ diff --git a/Packages/NB_FX/.git.backup/objects/17/3dffc8b5abf792fe801645e21b822d3d546036 b/Packages/NB_FX/.git.backup/objects/17/3dffc8b5abf792fe801645e21b822d3d546036 new file mode 100644 index 00000000..323dec4a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/17/3dffc8b5abf792fe801645e21b822d3d546036 differ diff --git a/Packages/NB_FX/.git.backup/objects/17/4c17c2495a3529e48560af09f839e30f10e984 b/Packages/NB_FX/.git.backup/objects/17/4c17c2495a3529e48560af09f839e30f10e984 new file mode 100644 index 00000000..2b8d623b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/17/4c17c2495a3529e48560af09f839e30f10e984 differ diff --git a/Packages/NB_FX/.git.backup/objects/17/5614a05620c6254097cc12407c0790889d2f2b b/Packages/NB_FX/.git.backup/objects/17/5614a05620c6254097cc12407c0790889d2f2b new file mode 100644 index 00000000..275a1bff Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/17/5614a05620c6254097cc12407c0790889d2f2b differ diff --git a/Packages/NB_FX/.git.backup/objects/18/134483957d1d6a892b6a5d541be6f667a31857 b/Packages/NB_FX/.git.backup/objects/18/134483957d1d6a892b6a5d541be6f667a31857 new file mode 100644 index 00000000..21ed8cda Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/18/134483957d1d6a892b6a5d541be6f667a31857 differ diff --git a/Packages/NB_FX/.git.backup/objects/18/1b4dd750feb03ce9b69dac364f0853549bf1c9 b/Packages/NB_FX/.git.backup/objects/18/1b4dd750feb03ce9b69dac364f0853549bf1c9 new file mode 100644 index 00000000..ccb2da7c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/18/1b4dd750feb03ce9b69dac364f0853549bf1c9 differ diff --git a/Packages/NB_FX/.git.backup/objects/18/83b14507ae50f472948dcbc6c985c2ad2c699f b/Packages/NB_FX/.git.backup/objects/18/83b14507ae50f472948dcbc6c985c2ad2c699f new file mode 100644 index 00000000..342b217b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/18/83b14507ae50f472948dcbc6c985c2ad2c699f differ diff --git a/Packages/NB_FX/.git.backup/objects/19/070e4fcb34d060164a7263d71a95a59a34143b b/Packages/NB_FX/.git.backup/objects/19/070e4fcb34d060164a7263d71a95a59a34143b new file mode 100644 index 00000000..8c8afac2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/19/070e4fcb34d060164a7263d71a95a59a34143b differ diff --git a/Packages/NB_FX/.git.backup/objects/19/0c6c915100ad9466805c53e10cb672655f9951 b/Packages/NB_FX/.git.backup/objects/19/0c6c915100ad9466805c53e10cb672655f9951 new file mode 100644 index 00000000..e8ea6bd0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/19/0c6c915100ad9466805c53e10cb672655f9951 differ diff --git a/Packages/NB_FX/.git.backup/objects/19/92b9d3ff8bcafd8490f8677875188e78bd4ed9 b/Packages/NB_FX/.git.backup/objects/19/92b9d3ff8bcafd8490f8677875188e78bd4ed9 new file mode 100644 index 00000000..1e63025c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/19/92b9d3ff8bcafd8490f8677875188e78bd4ed9 differ diff --git a/Packages/NB_FX/.git.backup/objects/19/a4286bccd1683e50d838a6e1ae175a2ddebc29 b/Packages/NB_FX/.git.backup/objects/19/a4286bccd1683e50d838a6e1ae175a2ddebc29 new file mode 100644 index 00000000..7d61fea4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/19/a4286bccd1683e50d838a6e1ae175a2ddebc29 differ diff --git a/Packages/NB_FX/.git.backup/objects/19/afa5144a6f2b5e0d8da2cca56340ea09c875ce b/Packages/NB_FX/.git.backup/objects/19/afa5144a6f2b5e0d8da2cca56340ea09c875ce new file mode 100644 index 00000000..e8d329fe Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/19/afa5144a6f2b5e0d8da2cca56340ea09c875ce differ diff --git a/Packages/NB_FX/.git.backup/objects/19/ca0fe2edb1af79643fbe9355ccfb8cd8c28e54 b/Packages/NB_FX/.git.backup/objects/19/ca0fe2edb1af79643fbe9355ccfb8cd8c28e54 new file mode 100644 index 00000000..86418e20 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/19/ca0fe2edb1af79643fbe9355ccfb8cd8c28e54 differ diff --git a/Packages/NB_FX/.git.backup/objects/19/e2b34f1915d8f1db4444d2957614ad57d7b4e1 b/Packages/NB_FX/.git.backup/objects/19/e2b34f1915d8f1db4444d2957614ad57d7b4e1 new file mode 100644 index 00000000..d9bdc99e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/19/e2b34f1915d8f1db4444d2957614ad57d7b4e1 differ diff --git a/Packages/NB_FX/.git.backup/objects/1a/7c7bc7326c1e544df9af81d95d561720490543 b/Packages/NB_FX/.git.backup/objects/1a/7c7bc7326c1e544df9af81d95d561720490543 new file mode 100644 index 00000000..75d22011 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1a/7c7bc7326c1e544df9af81d95d561720490543 differ diff --git a/Packages/NB_FX/.git.backup/objects/1a/8301417fbc9186b78b56a854ea8e5fea081d1f b/Packages/NB_FX/.git.backup/objects/1a/8301417fbc9186b78b56a854ea8e5fea081d1f new file mode 100644 index 00000000..41e41e00 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1a/8301417fbc9186b78b56a854ea8e5fea081d1f differ diff --git a/Packages/NB_FX/.git.backup/objects/1a/b866d2f21a72579aa0a0ef806ea209e87023eb b/Packages/NB_FX/.git.backup/objects/1a/b866d2f21a72579aa0a0ef806ea209e87023eb new file mode 100644 index 00000000..74a93f0c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1a/b866d2f21a72579aa0a0ef806ea209e87023eb differ diff --git a/Packages/NB_FX/.git.backup/objects/1a/f4ad985a113b55e9d76578843b4790a3f17898 b/Packages/NB_FX/.git.backup/objects/1a/f4ad985a113b55e9d76578843b4790a3f17898 new file mode 100644 index 00000000..4d95a5c0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1a/f4ad985a113b55e9d76578843b4790a3f17898 differ diff --git a/Packages/NB_FX/.git.backup/objects/1b/39a3c9bc173d91ae78ee3a3d715399f6177f6c b/Packages/NB_FX/.git.backup/objects/1b/39a3c9bc173d91ae78ee3a3d715399f6177f6c new file mode 100644 index 00000000..a464ab2b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1b/39a3c9bc173d91ae78ee3a3d715399f6177f6c differ diff --git a/Packages/NB_FX/.git.backup/objects/1b/57a1436865eb5d3675ba0b606c57ae7758005c b/Packages/NB_FX/.git.backup/objects/1b/57a1436865eb5d3675ba0b606c57ae7758005c new file mode 100644 index 00000000..f5b8ad0c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1b/57a1436865eb5d3675ba0b606c57ae7758005c differ diff --git a/Packages/NB_FX/.git.backup/objects/1b/764984a3c8505ec03a011c11d456bbdeb16ac8 b/Packages/NB_FX/.git.backup/objects/1b/764984a3c8505ec03a011c11d456bbdeb16ac8 new file mode 100644 index 00000000..b2fec725 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/1b/764984a3c8505ec03a011c11d456bbdeb16ac8 @@ -0,0 +1,3 @@ +x+)JMU054g040031QK,I,))L*-I-fH[׮;{m9;QH*3R'>=Rfӓij^U_\PZ\Zqe{tD;5W P@WϰGϳG^̿]d!WiĔԢb{6,qJBp骟 ܅ *dviZ+թ"[bptӌ %j#º7{_Ί֍fxȂ0c9԰O蘫 5/41Rn -,s[ N:լ Cƪ!嬺n͟*zN\P[ +S +עd8k˅ǢR"ϥ->Fxv`^հ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/1c/09a9d5cc842f5ea6840c8047e48d05ba219d92 b/Packages/NB_FX/.git.backup/objects/1c/09a9d5cc842f5ea6840c8047e48d05ba219d92 new file mode 100644 index 00000000..fbc63a7a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1c/09a9d5cc842f5ea6840c8047e48d05ba219d92 differ diff --git a/Packages/NB_FX/.git.backup/objects/1c/2aad14fe901c41e242777d1eaef96186a374e6 b/Packages/NB_FX/.git.backup/objects/1c/2aad14fe901c41e242777d1eaef96186a374e6 new file mode 100644 index 00000000..541b5609 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/1c/2aad14fe901c41e242777d1eaef96186a374e6 @@ -0,0 +1,2 @@ +x+)JMU02`040031QpM,/M-IdX.t ^?^z|a}Q b`T3DV_dOB *+M^MOnӅYte1U/Ҟl['=h4jRpFbJ*EY2s2dq *vci +W,̝jV \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/1c/592f3bf3d524c103c4ab45047da1e8d02e611a b/Packages/NB_FX/.git.backup/objects/1c/592f3bf3d524c103c4ab45047da1e8d02e611a new file mode 100644 index 00000000..117a900c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1c/592f3bf3d524c103c4ab45047da1e8d02e611a differ diff --git a/Packages/NB_FX/.git.backup/objects/1c/ac19c96a3c67fad56d85156f8f4e4a136c8f35 b/Packages/NB_FX/.git.backup/objects/1c/ac19c96a3c67fad56d85156f8f4e4a136c8f35 new file mode 100644 index 00000000..9730fb68 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1c/ac19c96a3c67fad56d85156f8f4e4a136c8f35 differ diff --git a/Packages/NB_FX/.git.backup/objects/1c/f7ef96085482a34a3cd356aad0fa3a4ef1bfe8 b/Packages/NB_FX/.git.backup/objects/1c/f7ef96085482a34a3cd356aad0fa3a4ef1bfe8 new file mode 100644 index 00000000..e6df7673 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1c/f7ef96085482a34a3cd356aad0fa3a4ef1bfe8 differ diff --git a/Packages/NB_FX/.git.backup/objects/1c/fa1eebb650dd8c0de9b49709febc1cbdd1a0f2 b/Packages/NB_FX/.git.backup/objects/1c/fa1eebb650dd8c0de9b49709febc1cbdd1a0f2 new file mode 100644 index 00000000..a66be95e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1c/fa1eebb650dd8c0de9b49709febc1cbdd1a0f2 differ diff --git a/Packages/NB_FX/.git.backup/objects/1d/8994c4cc70acf238e0a4264e10a6618c8b5d60 b/Packages/NB_FX/.git.backup/objects/1d/8994c4cc70acf238e0a4264e10a6618c8b5d60 new file mode 100644 index 00000000..a160b1a6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1d/8994c4cc70acf238e0a4264e10a6618c8b5d60 differ diff --git a/Packages/NB_FX/.git.backup/objects/1e/420d45a59fcbdc341512fd5f0bf9861bed6bac b/Packages/NB_FX/.git.backup/objects/1e/420d45a59fcbdc341512fd5f0bf9861bed6bac new file mode 100644 index 00000000..29d48419 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1e/420d45a59fcbdc341512fd5f0bf9861bed6bac differ diff --git a/Packages/NB_FX/.git.backup/objects/1e/54b1b95e1e23464801e950dadd558e5bd98b7d b/Packages/NB_FX/.git.backup/objects/1e/54b1b95e1e23464801e950dadd558e5bd98b7d new file mode 100644 index 00000000..a431b734 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1e/54b1b95e1e23464801e950dadd558e5bd98b7d differ diff --git a/Packages/NB_FX/.git.backup/objects/1e/61cf052467fc7cbcddace4b99f9c12937863a8 b/Packages/NB_FX/.git.backup/objects/1e/61cf052467fc7cbcddace4b99f9c12937863a8 new file mode 100644 index 00000000..eeb1eac1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1e/61cf052467fc7cbcddace4b99f9c12937863a8 differ diff --git a/Packages/NB_FX/.git.backup/objects/1e/79822bbfd33c653697042bd0c05483d28eb04c b/Packages/NB_FX/.git.backup/objects/1e/79822bbfd33c653697042bd0c05483d28eb04c new file mode 100644 index 00000000..6bc9747f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1e/79822bbfd33c653697042bd0c05483d28eb04c differ diff --git a/Packages/NB_FX/.git.backup/objects/1f/2cfaf7c0caa12a9627b1d3953d2138c47fb457 b/Packages/NB_FX/.git.backup/objects/1f/2cfaf7c0caa12a9627b1d3953d2138c47fb457 new file mode 100644 index 00000000..fd8a4592 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1f/2cfaf7c0caa12a9627b1d3953d2138c47fb457 differ diff --git a/Packages/NB_FX/.git.backup/objects/1f/474c26740630fee4c338db6626672bfb385ed5 b/Packages/NB_FX/.git.backup/objects/1f/474c26740630fee4c338db6626672bfb385ed5 new file mode 100644 index 00000000..6053aafa Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1f/474c26740630fee4c338db6626672bfb385ed5 differ diff --git a/Packages/NB_FX/.git.backup/objects/1f/4af6d7cf27f1dd3422d104c67482648c6bca43 b/Packages/NB_FX/.git.backup/objects/1f/4af6d7cf27f1dd3422d104c67482648c6bca43 new file mode 100644 index 00000000..6caa12d1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1f/4af6d7cf27f1dd3422d104c67482648c6bca43 differ diff --git a/Packages/NB_FX/.git.backup/objects/1f/849e0959ac27646f018303b2f810371ff3730f b/Packages/NB_FX/.git.backup/objects/1f/849e0959ac27646f018303b2f810371ff3730f new file mode 100644 index 00000000..ab60e132 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1f/849e0959ac27646f018303b2f810371ff3730f differ diff --git a/Packages/NB_FX/.git.backup/objects/1f/922b5ad9725ca73d1af17935c216048f32e1fc b/Packages/NB_FX/.git.backup/objects/1f/922b5ad9725ca73d1af17935c216048f32e1fc new file mode 100644 index 00000000..c99de471 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1f/922b5ad9725ca73d1af17935c216048f32e1fc differ diff --git a/Packages/NB_FX/.git.backup/objects/1f/9ecd0ca44f9f36b383b04c654c009ebebf5ec0 b/Packages/NB_FX/.git.backup/objects/1f/9ecd0ca44f9f36b383b04c654c009ebebf5ec0 new file mode 100644 index 00000000..1ee9aabc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1f/9ecd0ca44f9f36b383b04c654c009ebebf5ec0 differ diff --git a/Packages/NB_FX/.git.backup/objects/1f/bd641865a4bba48e5b2640f8d27814d1124f93 b/Packages/NB_FX/.git.backup/objects/1f/bd641865a4bba48e5b2640f8d27814d1124f93 new file mode 100644 index 00000000..aa52b030 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1f/bd641865a4bba48e5b2640f8d27814d1124f93 differ diff --git a/Packages/NB_FX/.git.backup/objects/1f/ea5579e2ba253eaa8e42b83dc8e740931a7974 b/Packages/NB_FX/.git.backup/objects/1f/ea5579e2ba253eaa8e42b83dc8e740931a7974 new file mode 100644 index 00000000..170bcfcf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/1f/ea5579e2ba253eaa8e42b83dc8e740931a7974 differ diff --git a/Packages/NB_FX/.git.backup/objects/20/31e5e3bf478bfadc592a019179f83abfe69ac9 b/Packages/NB_FX/.git.backup/objects/20/31e5e3bf478bfadc592a019179f83abfe69ac9 new file mode 100644 index 00000000..1f3510e0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/20/31e5e3bf478bfadc592a019179f83abfe69ac9 differ diff --git a/Packages/NB_FX/.git.backup/objects/20/71fb6189fc9409f4ee8a536019d783227ac8ac b/Packages/NB_FX/.git.backup/objects/20/71fb6189fc9409f4ee8a536019d783227ac8ac new file mode 100644 index 00000000..ceb27d80 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/20/71fb6189fc9409f4ee8a536019d783227ac8ac differ diff --git a/Packages/NB_FX/.git.backup/objects/20/740018f0c2018041c09c3de2dbd86805f3dcc9 b/Packages/NB_FX/.git.backup/objects/20/740018f0c2018041c09c3de2dbd86805f3dcc9 new file mode 100644 index 00000000..3619aa91 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/20/740018f0c2018041c09c3de2dbd86805f3dcc9 differ diff --git a/Packages/NB_FX/.git.backup/objects/20/7ca46b5c85f22ffb31c7c7fcfedc22f2d606b4 b/Packages/NB_FX/.git.backup/objects/20/7ca46b5c85f22ffb31c7c7fcfedc22f2d606b4 new file mode 100644 index 00000000..e15e5d1f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/20/7ca46b5c85f22ffb31c7c7fcfedc22f2d606b4 differ diff --git a/Packages/NB_FX/.git.backup/objects/20/cf9d0c6f81d58604ca0c19c7f6fdfb60fccbbb b/Packages/NB_FX/.git.backup/objects/20/cf9d0c6f81d58604ca0c19c7f6fdfb60fccbbb new file mode 100644 index 00000000..ade59583 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/20/cf9d0c6f81d58604ca0c19c7f6fdfb60fccbbb differ diff --git a/Packages/NB_FX/.git.backup/objects/20/d09820ca74a7af6c6f6976e876d52a6b6c8093 b/Packages/NB_FX/.git.backup/objects/20/d09820ca74a7af6c6f6976e876d52a6b6c8093 new file mode 100644 index 00000000..65f39d3c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/20/d09820ca74a7af6c6f6976e876d52a6b6c8093 differ diff --git a/Packages/NB_FX/.git.backup/objects/21/0ec7672a56fe0ba2d1e03a3f0c74071d160f3b b/Packages/NB_FX/.git.backup/objects/21/0ec7672a56fe0ba2d1e03a3f0c74071d160f3b new file mode 100644 index 00000000..1a59f64e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/21/0ec7672a56fe0ba2d1e03a3f0c74071d160f3b differ diff --git a/Packages/NB_FX/.git.backup/objects/21/121f945d07aad0863831fcfefe47dca07772cf b/Packages/NB_FX/.git.backup/objects/21/121f945d07aad0863831fcfefe47dca07772cf new file mode 100644 index 00000000..4db97215 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/21/121f945d07aad0863831fcfefe47dca07772cf differ diff --git a/Packages/NB_FX/.git.backup/objects/22/1f44a44192502b47cfd9e26ebd23bc5487b5fc b/Packages/NB_FX/.git.backup/objects/22/1f44a44192502b47cfd9e26ebd23bc5487b5fc new file mode 100644 index 00000000..986da6eb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/22/1f44a44192502b47cfd9e26ebd23bc5487b5fc differ diff --git a/Packages/NB_FX/.git.backup/objects/22/49db32cedd4c5220554531cc45cc679b4d71d8 b/Packages/NB_FX/.git.backup/objects/22/49db32cedd4c5220554531cc45cc679b4d71d8 new file mode 100644 index 00000000..d571639d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/22/49db32cedd4c5220554531cc45cc679b4d71d8 differ diff --git a/Packages/NB_FX/.git.backup/objects/22/66d6e3af568d2c0b2cd438e8c28c6f87824234 b/Packages/NB_FX/.git.backup/objects/22/66d6e3af568d2c0b2cd438e8c28c6f87824234 new file mode 100644 index 00000000..9760175b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/22/66d6e3af568d2c0b2cd438e8c28c6f87824234 differ diff --git a/Packages/NB_FX/.git.backup/objects/22/c263e4f37ebe82a12de8ca444b136e42bb614b b/Packages/NB_FX/.git.backup/objects/22/c263e4f37ebe82a12de8ca444b136e42bb614b new file mode 100644 index 00000000..05ce0e01 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/22/c263e4f37ebe82a12de8ca444b136e42bb614b @@ -0,0 +1,5 @@ +x+)JMU016g040031Qs +/. (ON-.KM-Idpʸ~=:"KV횫`gf{ù~[eƢ +ޯ=-fg$C ݳaSKW\'.ܾf(T!Rq A?|I8])Zn8#Ww_XfOY1_غь3b[Wp^YMo; QAy@7ddTB|Eb [{W^yj!Fc 2؝ _l{{R5P[ +S +עd8k˅ǢR"ϥ->Fxv` \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/22/fd55639f5c3297c87e8cd9977b0871c5904457 b/Packages/NB_FX/.git.backup/objects/22/fd55639f5c3297c87e8cd9977b0871c5904457 new file mode 100644 index 00000000..160d0ac7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/22/fd55639f5c3297c87e8cd9977b0871c5904457 differ diff --git a/Packages/NB_FX/.git.backup/objects/23/a75958a03f2e9c528c52ff2ed37bc79b17e237 b/Packages/NB_FX/.git.backup/objects/23/a75958a03f2e9c528c52ff2ed37bc79b17e237 new file mode 100644 index 00000000..98696305 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/23/a75958a03f2e9c528c52ff2ed37bc79b17e237 differ diff --git a/Packages/NB_FX/.git.backup/objects/23/ab2bee37b30df356ae701d422bdbda15c1437c b/Packages/NB_FX/.git.backup/objects/23/ab2bee37b30df356ae701d422bdbda15c1437c new file mode 100644 index 00000000..3cb99502 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/23/ab2bee37b30df356ae701d422bdbda15c1437c differ diff --git a/Packages/NB_FX/.git.backup/objects/24/9f2312541e59d2a98c0813c972b813eeb7d058 b/Packages/NB_FX/.git.backup/objects/24/9f2312541e59d2a98c0813c972b813eeb7d058 new file mode 100644 index 00000000..0b9b8cf9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/24/9f2312541e59d2a98c0813c972b813eeb7d058 differ diff --git a/Packages/NB_FX/.git.backup/objects/25/432db690eeb69980a3af1aa40498d5fdfe99ed b/Packages/NB_FX/.git.backup/objects/25/432db690eeb69980a3af1aa40498d5fdfe99ed new file mode 100644 index 00000000..d4094d72 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/25/432db690eeb69980a3af1aa40498d5fdfe99ed differ diff --git a/Packages/NB_FX/.git.backup/objects/25/61d73ae5b1e400ba031e6b2d92b30bd5e414bb b/Packages/NB_FX/.git.backup/objects/25/61d73ae5b1e400ba031e6b2d92b30bd5e414bb new file mode 100644 index 00000000..f2eda503 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/25/61d73ae5b1e400ba031e6b2d92b30bd5e414bb differ diff --git a/Packages/NB_FX/.git.backup/objects/25/868051a783e530eda0821962ef7bd74ac0c8d1 b/Packages/NB_FX/.git.backup/objects/25/868051a783e530eda0821962ef7bd74ac0c8d1 new file mode 100644 index 00000000..f70b6f90 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/25/868051a783e530eda0821962ef7bd74ac0c8d1 differ diff --git a/Packages/NB_FX/.git.backup/objects/25/cccc13f07a646c5dbb7a76fc51383605c0827a b/Packages/NB_FX/.git.backup/objects/25/cccc13f07a646c5dbb7a76fc51383605c0827a new file mode 100644 index 00000000..660fe38b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/25/cccc13f07a646c5dbb7a76fc51383605c0827a differ diff --git a/Packages/NB_FX/.git.backup/objects/26/39b83d980764874f6a8d19e25123c99b3dc046 b/Packages/NB_FX/.git.backup/objects/26/39b83d980764874f6a8d19e25123c99b3dc046 new file mode 100644 index 00000000..e3af9c8a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/26/39b83d980764874f6a8d19e25123c99b3dc046 differ diff --git a/Packages/NB_FX/.git.backup/objects/26/4b2694a998e9b0750e62fb7a0a704777cf625c b/Packages/NB_FX/.git.backup/objects/26/4b2694a998e9b0750e62fb7a0a704777cf625c new file mode 100644 index 00000000..5893363b --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/26/4b2694a998e9b0750e62fb7a0a704777cf625c @@ -0,0 +1,2 @@ +x]J1=S#e ":ID2$^O\*yYcCŒ-[;v΍<~&,=/fx,RD#s:wxi.Jj| +X'yƊ_ |rAdEu kxP|UwuXؒn rsHx ٙuF?qR \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/26/4d7f99c2749cf00c82b076fa536f7c3e023ad1 b/Packages/NB_FX/.git.backup/objects/26/4d7f99c2749cf00c82b076fa536f7c3e023ad1 new file mode 100644 index 00000000..74d1fcb0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/26/4d7f99c2749cf00c82b076fa536f7c3e023ad1 differ diff --git a/Packages/NB_FX/.git.backup/objects/26/bfbd0ae2fee2d6a36961d01d6b84d89b9e833a b/Packages/NB_FX/.git.backup/objects/26/bfbd0ae2fee2d6a36961d01d6b84d89b9e833a new file mode 100644 index 00000000..e3632b9d --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/26/bfbd0ae2fee2d6a36961d01d6b84d89b9e833a @@ -0,0 +1 @@ +xu= 0E+dꢫ~)kHҤާ:]roc nQp.U oh= \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/27/20ed3fd387732be46fbfc9a03a7bb70f727d1f b/Packages/NB_FX/.git.backup/objects/27/20ed3fd387732be46fbfc9a03a7bb70f727d1f new file mode 100644 index 00000000..28ee199b --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/27/20ed3fd387732be46fbfc9a03a7bb70f727d1f @@ -0,0 +1 @@ +x]J1=S# kpgrE؃NE"DIWļΌw>D4;SCx^!Z}+(c@vGAhWMS-ʂln!Z=o7ƹVǞ\ĉWCW0R \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/27/3bcf011abb088047d0ee1a6508a422d3ece9c3 b/Packages/NB_FX/.git.backup/objects/27/3bcf011abb088047d0ee1a6508a422d3ece9c3 new file mode 100644 index 00000000..47ed4b2a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/27/3bcf011abb088047d0ee1a6508a422d3ece9c3 differ diff --git a/Packages/NB_FX/.git.backup/objects/27/760d32852862dd7671e1402ae5f9f135ab30ae b/Packages/NB_FX/.git.backup/objects/27/760d32852862dd7671e1402ae5f9f135ab30ae new file mode 100644 index 00000000..5b9d7cf4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/27/760d32852862dd7671e1402ae5f9f135ab30ae differ diff --git a/Packages/NB_FX/.git.backup/objects/28/1815638c001346e33ef31cfa2a63cbd971671a b/Packages/NB_FX/.git.backup/objects/28/1815638c001346e33ef31cfa2a63cbd971671a new file mode 100644 index 00000000..dab9c260 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/28/1815638c001346e33ef31cfa2a63cbd971671a differ diff --git a/Packages/NB_FX/.git.backup/objects/28/95e1d17551d5c41dab415ae0720c79d0d819c6 b/Packages/NB_FX/.git.backup/objects/28/95e1d17551d5c41dab415ae0720c79d0d819c6 new file mode 100644 index 00000000..167b50b8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/28/95e1d17551d5c41dab415ae0720c79d0d819c6 differ diff --git a/Packages/NB_FX/.git.backup/objects/28/9fccee538bd373c721d6d35e462eb6fcbb2197 b/Packages/NB_FX/.git.backup/objects/28/9fccee538bd373c721d6d35e462eb6fcbb2197 new file mode 100644 index 00000000..2ee0457b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/28/9fccee538bd373c721d6d35e462eb6fcbb2197 differ diff --git a/Packages/NB_FX/.git.backup/objects/28/b2271a39603b996012641169e70303a2988a08 b/Packages/NB_FX/.git.backup/objects/28/b2271a39603b996012641169e70303a2988a08 new file mode 100644 index 00000000..62953e0c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/28/b2271a39603b996012641169e70303a2988a08 differ diff --git a/Packages/NB_FX/.git.backup/objects/28/ba928add46a24dae059ecc93d454afbdd11ba2 b/Packages/NB_FX/.git.backup/objects/28/ba928add46a24dae059ecc93d454afbdd11ba2 new file mode 100644 index 00000000..3ff9be51 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/28/ba928add46a24dae059ecc93d454afbdd11ba2 differ diff --git a/Packages/NB_FX/.git.backup/objects/29/da738d22c400d5c2e65b87767841446d77dd0b b/Packages/NB_FX/.git.backup/objects/29/da738d22c400d5c2e65b87767841446d77dd0b new file mode 100644 index 00000000..cce081d8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/29/da738d22c400d5c2e65b87767841446d77dd0b differ diff --git a/Packages/NB_FX/.git.backup/objects/2a/8316396dc8ef92ccc34e2599876eb432d72bd3 b/Packages/NB_FX/.git.backup/objects/2a/8316396dc8ef92ccc34e2599876eb432d72bd3 new file mode 100644 index 00000000..4e0f5cdd Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2a/8316396dc8ef92ccc34e2599876eb432d72bd3 differ diff --git a/Packages/NB_FX/.git.backup/objects/2a/b709d3b5d051f21149ff5a0c56abfc1a9755bf b/Packages/NB_FX/.git.backup/objects/2a/b709d3b5d051f21149ff5a0c56abfc1a9755bf new file mode 100644 index 00000000..30134565 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/2a/b709d3b5d051f21149ff5a0c56abfc1a9755bf @@ -0,0 +1 @@ +xK0=xRR:) /vp!VY cOAsiK?IEpBrfzK2˜dFI\Q$>}l-I_hg)cŤsW*\ 3](v;*óE[դ\2w+XL'פEQKd:|]i-;@ؒʹ0<1_#LA]O!hGHMo3WyϺWiQgA`ZdyY㽪8,?RWq?ݭu \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/2a/d184c0f693022042c32465e2bbbd04c7a02bfe b/Packages/NB_FX/.git.backup/objects/2a/d184c0f693022042c32465e2bbbd04c7a02bfe new file mode 100644 index 00000000..4430548d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2a/d184c0f693022042c32465e2bbbd04c7a02bfe differ diff --git a/Packages/NB_FX/.git.backup/objects/2a/fec1ecfa1bc19938600208364b84b1a5967b7f b/Packages/NB_FX/.git.backup/objects/2a/fec1ecfa1bc19938600208364b84b1a5967b7f new file mode 100644 index 00000000..5ba3c88f --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/2a/fec1ecfa1bc19938600208364b84b1a5967b7f @@ -0,0 +1,6 @@ +x+)JMU016g040031Qs +/. (ON-.KM-Idpʸ~=:"KV횫`gP>(;T%J߼< 7;8#1%b K\>w0C +9w)fg،EM3gdy I|9+& [7qF { +P"J@8(5В̜̒J1HLpat+/?Xͺ`9h^HL+lrIʏRaP[ +S +עd8k˅ǢR"ϥ->Fxv`Z \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/2b/04de3077c90c0f701ba36388b9dfaffb7f8ef3 b/Packages/NB_FX/.git.backup/objects/2b/04de3077c90c0f701ba36388b9dfaffb7f8ef3 new file mode 100644 index 00000000..999472c0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2b/04de3077c90c0f701ba36388b9dfaffb7f8ef3 differ diff --git a/Packages/NB_FX/.git.backup/objects/2b/790f672838dd749e087c78d1513e62666b4e92 b/Packages/NB_FX/.git.backup/objects/2b/790f672838dd749e087c78d1513e62666b4e92 new file mode 100644 index 00000000..762c8542 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2b/790f672838dd749e087c78d1513e62666b4e92 differ diff --git a/Packages/NB_FX/.git.backup/objects/2b/9a57086a929640c3409e0c4acdf34e2af8ae41 b/Packages/NB_FX/.git.backup/objects/2b/9a57086a929640c3409e0c4acdf34e2af8ae41 new file mode 100644 index 00000000..6de92f6b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2b/9a57086a929640c3409e0c4acdf34e2af8ae41 differ diff --git a/Packages/NB_FX/.git.backup/objects/2b/f3aedfc938f60c06ca961c74f518e5dfbdadf7 b/Packages/NB_FX/.git.backup/objects/2b/f3aedfc938f60c06ca961c74f518e5dfbdadf7 new file mode 100644 index 00000000..070a0f04 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2b/f3aedfc938f60c06ca961c74f518e5dfbdadf7 differ diff --git a/Packages/NB_FX/.git.backup/objects/2c/5d92384a63bedf9a972162681a602eb3323e15 b/Packages/NB_FX/.git.backup/objects/2c/5d92384a63bedf9a972162681a602eb3323e15 new file mode 100644 index 00000000..9e471e21 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2c/5d92384a63bedf9a972162681a602eb3323e15 differ diff --git a/Packages/NB_FX/.git.backup/objects/2c/8b2708d66d26305b56b55e83bea20a80d3ecca b/Packages/NB_FX/.git.backup/objects/2c/8b2708d66d26305b56b55e83bea20a80d3ecca new file mode 100644 index 00000000..97a77638 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2c/8b2708d66d26305b56b55e83bea20a80d3ecca differ diff --git a/Packages/NB_FX/.git.backup/objects/2d/160d2130629f2a79269089dcfa50927014fe7a b/Packages/NB_FX/.git.backup/objects/2d/160d2130629f2a79269089dcfa50927014fe7a new file mode 100644 index 00000000..2d8867ba Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2d/160d2130629f2a79269089dcfa50927014fe7a differ diff --git a/Packages/NB_FX/.git.backup/objects/2e/766d4dc8f171410a2f8090f38850ddca552d32 b/Packages/NB_FX/.git.backup/objects/2e/766d4dc8f171410a2f8090f38850ddca552d32 new file mode 100644 index 00000000..5f44ef8d --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/2e/766d4dc8f171410a2f8090f38850ddca552d32 @@ -0,0 +1 @@ +x]͊1=S#̟(ÂW؃Гt$IʾxoGUM>N:O1gJŠn]m'i@kpԺnԸC<11%UЏ4IsV)9!YJ4Ir}JH#dD 0_2TE]="29K0>q7tF9XUhVQ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/2e/a3c7a363d8995638f20f5f9643f8d784c2710f b/Packages/NB_FX/.git.backup/objects/2e/a3c7a363d8995638f20f5f9643f8d784c2710f new file mode 100644 index 00000000..c0ec6dc2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2e/a3c7a363d8995638f20f5f9643f8d784c2710f differ diff --git a/Packages/NB_FX/.git.backup/objects/2e/f1dd3e5764d96e568ddd4765764a9565e53f84 b/Packages/NB_FX/.git.backup/objects/2e/f1dd3e5764d96e568ddd4765764a9565e53f84 new file mode 100644 index 00000000..28b3bf70 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2e/f1dd3e5764d96e568ddd4765764a9565e53f84 differ diff --git a/Packages/NB_FX/.git.backup/objects/2f/8217e95fd16a128774076f8c8856638690c087 b/Packages/NB_FX/.git.backup/objects/2f/8217e95fd16a128774076f8c8856638690c087 new file mode 100644 index 00000000..a7a3e584 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2f/8217e95fd16a128774076f8c8856638690c087 differ diff --git a/Packages/NB_FX/.git.backup/objects/2f/90864ad624fc62f5de043adc7f5b1ad666211d b/Packages/NB_FX/.git.backup/objects/2f/90864ad624fc62f5de043adc7f5b1ad666211d new file mode 100644 index 00000000..72c2a32d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/2f/90864ad624fc62f5de043adc7f5b1ad666211d differ diff --git a/Packages/NB_FX/.git.backup/objects/30/af202864afb3a0570226525c5ae1150c7912de b/Packages/NB_FX/.git.backup/objects/30/af202864afb3a0570226525c5ae1150c7912de new file mode 100644 index 00000000..481cede1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/30/af202864afb3a0570226525c5ae1150c7912de differ diff --git a/Packages/NB_FX/.git.backup/objects/30/b58bbc2ba398670f2b9f459f634c2b33bea956 b/Packages/NB_FX/.git.backup/objects/30/b58bbc2ba398670f2b9f459f634c2b33bea956 new file mode 100644 index 00000000..233111da Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/30/b58bbc2ba398670f2b9f459f634c2b33bea956 differ diff --git a/Packages/NB_FX/.git.backup/objects/30/de6e2ef97254d73b94845af4d1a85219a0b84b b/Packages/NB_FX/.git.backup/objects/30/de6e2ef97254d73b94845af4d1a85219a0b84b new file mode 100644 index 00000000..b3bcabe4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/30/de6e2ef97254d73b94845af4d1a85219a0b84b differ diff --git a/Packages/NB_FX/.git.backup/objects/31/4409068387c4a5cee9ee532361d16842fb3215 b/Packages/NB_FX/.git.backup/objects/31/4409068387c4a5cee9ee532361d16842fb3215 new file mode 100644 index 00000000..08941f5a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/31/4409068387c4a5cee9ee532361d16842fb3215 differ diff --git a/Packages/NB_FX/.git.backup/objects/31/5d1b951430929fd6a58497c2a36ee5a5af312f b/Packages/NB_FX/.git.backup/objects/31/5d1b951430929fd6a58497c2a36ee5a5af312f new file mode 100644 index 00000000..53bbd06d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/31/5d1b951430929fd6a58497c2a36ee5a5af312f differ diff --git a/Packages/NB_FX/.git.backup/objects/31/733c02e82c2548c01b152baad58b32af70a52a b/Packages/NB_FX/.git.backup/objects/31/733c02e82c2548c01b152baad58b32af70a52a new file mode 100644 index 00000000..e629104a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/31/733c02e82c2548c01b152baad58b32af70a52a differ diff --git a/Packages/NB_FX/.git.backup/objects/31/909557c4058a0888267fd2b4621e6111a39b63 b/Packages/NB_FX/.git.backup/objects/31/909557c4058a0888267fd2b4621e6111a39b63 new file mode 100644 index 00000000..84c4f978 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/31/909557c4058a0888267fd2b4621e6111a39b63 differ diff --git a/Packages/NB_FX/.git.backup/objects/31/b430949f11a5c35c5140f1b2610a11155c44a8 b/Packages/NB_FX/.git.backup/objects/31/b430949f11a5c35c5140f1b2610a11155c44a8 new file mode 100644 index 00000000..54459b4e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/31/b430949f11a5c35c5140f1b2610a11155c44a8 differ diff --git a/Packages/NB_FX/.git.backup/objects/31/da26e69becf673ff4020325d7507e9a146c40f b/Packages/NB_FX/.git.backup/objects/31/da26e69becf673ff4020325d7507e9a146c40f new file mode 100644 index 00000000..abcda988 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/31/da26e69becf673ff4020325d7507e9a146c40f differ diff --git a/Packages/NB_FX/.git.backup/objects/31/ec7fffa98810cc4445ea591abc672062f1b05d b/Packages/NB_FX/.git.backup/objects/31/ec7fffa98810cc4445ea591abc672062f1b05d new file mode 100644 index 00000000..7fad6043 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/31/ec7fffa98810cc4445ea591abc672062f1b05d differ diff --git a/Packages/NB_FX/.git.backup/objects/32/237a29929c4823199484538519648fdf596a8c b/Packages/NB_FX/.git.backup/objects/32/237a29929c4823199484538519648fdf596a8c new file mode 100644 index 00000000..cb236868 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/32/237a29929c4823199484538519648fdf596a8c differ diff --git a/Packages/NB_FX/.git.backup/objects/32/608ca414d14a0cd1924a3c1190c29498a1be13 b/Packages/NB_FX/.git.backup/objects/32/608ca414d14a0cd1924a3c1190c29498a1be13 new file mode 100644 index 00000000..c847d6ba Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/32/608ca414d14a0cd1924a3c1190c29498a1be13 differ diff --git a/Packages/NB_FX/.git.backup/objects/32/8db0befbae495881d5e1f0b2e3b797253927e3 b/Packages/NB_FX/.git.backup/objects/32/8db0befbae495881d5e1f0b2e3b797253927e3 new file mode 100644 index 00000000..18346ee9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/32/8db0befbae495881d5e1f0b2e3b797253927e3 differ diff --git a/Packages/NB_FX/.git.backup/objects/33/0b87ac2f9a2f59794191904d03c487c97f6afc b/Packages/NB_FX/.git.backup/objects/33/0b87ac2f9a2f59794191904d03c487c97f6afc new file mode 100644 index 00000000..6c69be0f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/33/0b87ac2f9a2f59794191904d03c487c97f6afc differ diff --git a/Packages/NB_FX/.git.backup/objects/33/146d8e94b6df759466ae04671e51e3bf53e80c b/Packages/NB_FX/.git.backup/objects/33/146d8e94b6df759466ae04671e51e3bf53e80c new file mode 100644 index 00000000..e6129bf8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/33/146d8e94b6df759466ae04671e51e3bf53e80c differ diff --git a/Packages/NB_FX/.git.backup/objects/33/51c535d1359f0a2e54b61b002f23ba375c2f8e b/Packages/NB_FX/.git.backup/objects/33/51c535d1359f0a2e54b61b002f23ba375c2f8e new file mode 100644 index 00000000..4b5315de Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/33/51c535d1359f0a2e54b61b002f23ba375c2f8e differ diff --git a/Packages/NB_FX/.git.backup/objects/33/75a2fd7cc74664c75e3425b358a51b4ae669a0 b/Packages/NB_FX/.git.backup/objects/33/75a2fd7cc74664c75e3425b358a51b4ae669a0 new file mode 100644 index 00000000..e52513e1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/33/75a2fd7cc74664c75e3425b358a51b4ae669a0 differ diff --git a/Packages/NB_FX/.git.backup/objects/33/feba3017ac91f0e2c27792a8342ba3b45ddc11 b/Packages/NB_FX/.git.backup/objects/33/feba3017ac91f0e2c27792a8342ba3b45ddc11 new file mode 100644 index 00000000..00d73662 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/33/feba3017ac91f0e2c27792a8342ba3b45ddc11 differ diff --git a/Packages/NB_FX/.git.backup/objects/34/aaa862b589624028e0876b1cf91e09d1dc1a27 b/Packages/NB_FX/.git.backup/objects/34/aaa862b589624028e0876b1cf91e09d1dc1a27 new file mode 100644 index 00000000..cf7657a7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/34/aaa862b589624028e0876b1cf91e09d1dc1a27 differ diff --git a/Packages/NB_FX/.git.backup/objects/34/b7e5fc2d29e689bac5b377ddb66fade035643f b/Packages/NB_FX/.git.backup/objects/34/b7e5fc2d29e689bac5b377ddb66fade035643f new file mode 100644 index 00000000..6cf0004d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/34/b7e5fc2d29e689bac5b377ddb66fade035643f differ diff --git a/Packages/NB_FX/.git.backup/objects/34/ca8ee5d4b8a7f999541ada73a50dd5d0850cb0 b/Packages/NB_FX/.git.backup/objects/34/ca8ee5d4b8a7f999541ada73a50dd5d0850cb0 new file mode 100644 index 00000000..34c15a3c --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/34/ca8ee5d4b8a7f999541ada73a50dd5d0850cb0 @@ -0,0 +1,2 @@ +xA +0 {+t/" +#4y~e؁۲ nPZ*Z0zc1f2) ZMEX'6WJ8YA52Y6"c\>۴pyNgf,D 썕ɱR /uY]SABI$ȉ foH *۴6SO{E^@tK^Z!3D~o̖b}M^mIGq(M|\sL \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/3f/15ff3aa70ad074dac7c76a53ab800140360840 b/Packages/NB_FX/.git.backup/objects/3f/15ff3aa70ad074dac7c76a53ab800140360840 new file mode 100644 index 00000000..810cd281 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/3f/15ff3aa70ad074dac7c76a53ab800140360840 differ diff --git a/Packages/NB_FX/.git.backup/objects/3f/1ce74aa559a511a013b85ac8c4f6f2489c74c2 b/Packages/NB_FX/.git.backup/objects/3f/1ce74aa559a511a013b85ac8c4f6f2489c74c2 new file mode 100644 index 00000000..e93479ce Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/3f/1ce74aa559a511a013b85ac8c4f6f2489c74c2 differ diff --git a/Packages/NB_FX/.git.backup/objects/3f/21b5af78071ef5a53b0b977c036abeda3ce0dc b/Packages/NB_FX/.git.backup/objects/3f/21b5af78071ef5a53b0b977c036abeda3ce0dc new file mode 100644 index 00000000..4191b560 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/3f/21b5af78071ef5a53b0b977c036abeda3ce0dc @@ -0,0 +1 @@ +x]J1]SGHC,]hE7Nr")DbݽJ>9K* iBLx,u~AmdKzz[23C)h=aC8SS~QDO yf-FN G *_~%pˑs%%,-YM=}80OxЅDvFQ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/3f/730d0119865edd033a06612fc0fd9eae87bb54 b/Packages/NB_FX/.git.backup/objects/3f/730d0119865edd033a06612fc0fd9eae87bb54 new file mode 100644 index 00000000..8c8ca4c8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/3f/730d0119865edd033a06612fc0fd9eae87bb54 differ diff --git a/Packages/NB_FX/.git.backup/objects/40/19af85fb32fa5dd97debdb1ea54305489372e5 b/Packages/NB_FX/.git.backup/objects/40/19af85fb32fa5dd97debdb1ea54305489372e5 new file mode 100644 index 00000000..dfa1b1eb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/40/19af85fb32fa5dd97debdb1ea54305489372e5 differ diff --git a/Packages/NB_FX/.git.backup/objects/41/1274ce88c98bfbee5c5afdcee8bd7426d630f0 b/Packages/NB_FX/.git.backup/objects/41/1274ce88c98bfbee5c5afdcee8bd7426d630f0 new file mode 100644 index 00000000..2f07edf7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/41/1274ce88c98bfbee5c5afdcee8bd7426d630f0 differ diff --git a/Packages/NB_FX/.git.backup/objects/42/258eaa9211c82d2a1bd7a9592ab92c7a241e81 b/Packages/NB_FX/.git.backup/objects/42/258eaa9211c82d2a1bd7a9592ab92c7a241e81 new file mode 100644 index 00000000..b627201e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/42/258eaa9211c82d2a1bd7a9592ab92c7a241e81 differ diff --git a/Packages/NB_FX/.git.backup/objects/42/45222f124fe4a2c4b1ca0437ba03bfd32fbbf7 b/Packages/NB_FX/.git.backup/objects/42/45222f124fe4a2c4b1ca0437ba03bfd32fbbf7 new file mode 100644 index 00000000..a514c653 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/42/45222f124fe4a2c4b1ca0437ba03bfd32fbbf7 differ diff --git a/Packages/NB_FX/.git.backup/objects/42/71933982b668a1096b49b63bd2525017034e77 b/Packages/NB_FX/.git.backup/objects/42/71933982b668a1096b49b63bd2525017034e77 new file mode 100644 index 00000000..2eace267 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/42/71933982b668a1096b49b63bd2525017034e77 differ diff --git a/Packages/NB_FX/.git.backup/objects/42/b6c7a3348ca21fc18d47bf2cacc33635cbddfd b/Packages/NB_FX/.git.backup/objects/42/b6c7a3348ca21fc18d47bf2cacc33635cbddfd new file mode 100644 index 00000000..b1d64b13 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/42/b6c7a3348ca21fc18d47bf2cacc33635cbddfd differ diff --git a/Packages/NB_FX/.git.backup/objects/43/4eb3e0ea70ccc15e23169b5107c95b0d6b2b31 b/Packages/NB_FX/.git.backup/objects/43/4eb3e0ea70ccc15e23169b5107c95b0d6b2b31 new file mode 100644 index 00000000..75f47f98 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/43/4eb3e0ea70ccc15e23169b5107c95b0d6b2b31 differ diff --git a/Packages/NB_FX/.git.backup/objects/43/72ea7b4dec9a877159438d3a200e97808ee9c2 b/Packages/NB_FX/.git.backup/objects/43/72ea7b4dec9a877159438d3a200e97808ee9c2 new file mode 100644 index 00000000..3c3fb980 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/43/72ea7b4dec9a877159438d3a200e97808ee9c2 differ diff --git a/Packages/NB_FX/.git.backup/objects/45/4320c6dce52a10f2a2bd2c3725d93e7911d5ce b/Packages/NB_FX/.git.backup/objects/45/4320c6dce52a10f2a2bd2c3725d93e7911d5ce new file mode 100644 index 00000000..3e97cf67 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/45/4320c6dce52a10f2a2bd2c3725d93e7911d5ce differ diff --git a/Packages/NB_FX/.git.backup/objects/45/6a5b806ae52005df815e4b567f720ab2e8f5d5 b/Packages/NB_FX/.git.backup/objects/45/6a5b806ae52005df815e4b567f720ab2e8f5d5 new file mode 100644 index 00000000..0c364cf3 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/45/6a5b806ae52005df815e4b567f720ab2e8f5d5 @@ -0,0 +1 @@ +x]N1D+ˁK!H"QA{ld%DĿBt;OnBLx*ue9X%3-o%ahf ~(UP@O=2'[iCD{gTdJS讻.17aw [A{ G^YgdQ&R \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/45/8adc6c21482a7c73c14bb80e0340b6c9144e57 b/Packages/NB_FX/.git.backup/objects/45/8adc6c21482a7c73c14bb80e0340b6c9144e57 new file mode 100644 index 00000000..cd2bb899 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/45/8adc6c21482a7c73c14bb80e0340b6c9144e57 differ diff --git a/Packages/NB_FX/.git.backup/objects/45/ceb5d38f461a922705f50bae91831db1b2bc3c b/Packages/NB_FX/.git.backup/objects/45/ceb5d38f461a922705f50bae91831db1b2bc3c new file mode 100644 index 00000000..81e4312b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/45/ceb5d38f461a922705f50bae91831db1b2bc3c differ diff --git a/Packages/NB_FX/.git.backup/objects/47/172da5235137a554662cc25912dc6cf283a690 b/Packages/NB_FX/.git.backup/objects/47/172da5235137a554662cc25912dc6cf283a690 new file mode 100644 index 00000000..26e3049a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/47/172da5235137a554662cc25912dc6cf283a690 differ diff --git a/Packages/NB_FX/.git.backup/objects/47/27b663c531f66dec2a9d51b99844ef0128af7a b/Packages/NB_FX/.git.backup/objects/47/27b663c531f66dec2a9d51b99844ef0128af7a new file mode 100644 index 00000000..e4a64cf4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/47/27b663c531f66dec2a9d51b99844ef0128af7a differ diff --git a/Packages/NB_FX/.git.backup/objects/47/3eea29d6cae55fe87665deed15be92ea818a5a b/Packages/NB_FX/.git.backup/objects/47/3eea29d6cae55fe87665deed15be92ea818a5a new file mode 100644 index 00000000..ea02e716 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/47/3eea29d6cae55fe87665deed15be92ea818a5a differ diff --git a/Packages/NB_FX/.git.backup/objects/47/bbed141d418adaa29e378b3eab57eb1f8e795b b/Packages/NB_FX/.git.backup/objects/47/bbed141d418adaa29e378b3eab57eb1f8e795b new file mode 100644 index 00000000..db74be89 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/47/bbed141d418adaa29e378b3eab57eb1f8e795b differ diff --git a/Packages/NB_FX/.git.backup/objects/48/7b42267e6c69f8e2e32ad69e63831378a4d279 b/Packages/NB_FX/.git.backup/objects/48/7b42267e6c69f8e2e32ad69e63831378a4d279 new file mode 100644 index 00000000..ac7c697f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/48/7b42267e6c69f8e2e32ad69e63831378a4d279 differ diff --git a/Packages/NB_FX/.git.backup/objects/48/b0be0c9095a05cf78dfedd387b9cbf6f690ae4 b/Packages/NB_FX/.git.backup/objects/48/b0be0c9095a05cf78dfedd387b9cbf6f690ae4 new file mode 100644 index 00000000..26339b9d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/48/b0be0c9095a05cf78dfedd387b9cbf6f690ae4 differ diff --git a/Packages/NB_FX/.git.backup/objects/48/b83ed0a65bdcb7799f3ad6307ba3989cc0ce90 b/Packages/NB_FX/.git.backup/objects/48/b83ed0a65bdcb7799f3ad6307ba3989cc0ce90 new file mode 100644 index 00000000..e8551177 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/48/b83ed0a65bdcb7799f3ad6307ba3989cc0ce90 differ diff --git a/Packages/NB_FX/.git.backup/objects/49/83626217fe03ff4735f589f4c07014fd24e9bd b/Packages/NB_FX/.git.backup/objects/49/83626217fe03ff4735f589f4c07014fd24e9bd new file mode 100644 index 00000000..29a67d3f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/49/83626217fe03ff4735f589f4c07014fd24e9bd differ diff --git a/Packages/NB_FX/.git.backup/objects/49/b26efb03f33ec0adc1eaad1b66218a7875a877 b/Packages/NB_FX/.git.backup/objects/49/b26efb03f33ec0adc1eaad1b66218a7875a877 new file mode 100644 index 00000000..64809ee9 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/49/b26efb03f33ec0adc1eaad1b66218a7875a877 @@ -0,0 +1,2 @@ +x]j1]S#8 >41pRN +w^*nwXfDŽdH)\/ŧIu杦aS76Ƙ5f\SNuqJ"2DgsEWhA"[-_۪-ytݗ^ТmseMp)]xfX<Q \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/49/cedcd37e362460ed083860ad172bafa9966b13 b/Packages/NB_FX/.git.backup/objects/49/cedcd37e362460ed083860ad172bafa9966b13 new file mode 100644 index 00000000..48a85176 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/49/cedcd37e362460ed083860ad172bafa9966b13 differ diff --git a/Packages/NB_FX/.git.backup/objects/49/f58cdf6409620c5d821b13a285ddc5d58c06f1 b/Packages/NB_FX/.git.backup/objects/49/f58cdf6409620c5d821b13a285ddc5d58c06f1 new file mode 100644 index 00000000..6726b7b7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/49/f58cdf6409620c5d821b13a285ddc5d58c06f1 differ diff --git a/Packages/NB_FX/.git.backup/objects/4a/3b821ac977bbf66d125f9a45531cb0549df53c b/Packages/NB_FX/.git.backup/objects/4a/3b821ac977bbf66d125f9a45531cb0549df53c new file mode 100644 index 00000000..07746c76 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4a/3b821ac977bbf66d125f9a45531cb0549df53c differ diff --git a/Packages/NB_FX/.git.backup/objects/4a/5ae3f291c4e5386ea9520a03fd7dc6cb6d3478 b/Packages/NB_FX/.git.backup/objects/4a/5ae3f291c4e5386ea9520a03fd7dc6cb6d3478 new file mode 100644 index 00000000..166f7af1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4a/5ae3f291c4e5386ea9520a03fd7dc6cb6d3478 differ diff --git a/Packages/NB_FX/.git.backup/objects/4a/c433f85f4b6b50ea5268f8e081da7485cb703c b/Packages/NB_FX/.git.backup/objects/4a/c433f85f4b6b50ea5268f8e081da7485cb703c new file mode 100644 index 00000000..be981ead Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4a/c433f85f4b6b50ea5268f8e081da7485cb703c differ diff --git a/Packages/NB_FX/.git.backup/objects/4a/ea0f81f67b06db54768c50f8393a8327e921be b/Packages/NB_FX/.git.backup/objects/4a/ea0f81f67b06db54768c50f8393a8327e921be new file mode 100644 index 00000000..20ca00e5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4a/ea0f81f67b06db54768c50f8393a8327e921be differ diff --git a/Packages/NB_FX/.git.backup/objects/4b/45d401bb631640c039911bf271b400c7880677 b/Packages/NB_FX/.git.backup/objects/4b/45d401bb631640c039911bf271b400c7880677 new file mode 100644 index 00000000..61ecfb0a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4b/45d401bb631640c039911bf271b400c7880677 differ diff --git a/Packages/NB_FX/.git.backup/objects/4b/559f55e5261056bf1db7c300be17359ffb0053 b/Packages/NB_FX/.git.backup/objects/4b/559f55e5261056bf1db7c300be17359ffb0053 new file mode 100644 index 00000000..c2bff821 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4b/559f55e5261056bf1db7c300be17359ffb0053 differ diff --git a/Packages/NB_FX/.git.backup/objects/4b/ec50296946258d3e76d7fa3424178e7aa6f72c b/Packages/NB_FX/.git.backup/objects/4b/ec50296946258d3e76d7fa3424178e7aa6f72c new file mode 100644 index 00000000..f8061072 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4b/ec50296946258d3e76d7fa3424178e7aa6f72c differ diff --git a/Packages/NB_FX/.git.backup/objects/4c/b4ac32d474f2db53ecc3b23b2908abbbf7cc12 b/Packages/NB_FX/.git.backup/objects/4c/b4ac32d474f2db53ecc3b23b2908abbbf7cc12 new file mode 100644 index 00000000..69987419 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4c/b4ac32d474f2db53ecc3b23b2908abbbf7cc12 differ diff --git a/Packages/NB_FX/.git.backup/objects/4c/c213eb93825e069ce3dfde166774b040e6261c b/Packages/NB_FX/.git.backup/objects/4c/c213eb93825e069ce3dfde166774b040e6261c new file mode 100644 index 00000000..786d10f4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4c/c213eb93825e069ce3dfde166774b040e6261c differ diff --git a/Packages/NB_FX/.git.backup/objects/4c/c7be044755bd08ea5d14f6786c3851ddfa51c7 b/Packages/NB_FX/.git.backup/objects/4c/c7be044755bd08ea5d14f6786c3851ddfa51c7 new file mode 100644 index 00000000..cca16270 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/4c/c7be044755bd08ea5d14f6786c3851ddfa51c7 @@ -0,0 +1,5 @@ +x+)JMU016g040031Qs +/. (ON-.KM-Idpʸ~=:"KV횫`gP(g +w] כNZT 1tφ%?NI.]sTp~P F^xMOWTn8#Ww_XfOY1_غь3bDNggXg PȆQAy@7ddTB|Eb [{W^yj!Fc 2؝ _l{{R5P[ +S +עd8k˅ǢR"ϥ->Fxv`*< \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/4d/56db7248df5a109716fe14e491ab0191aa3734 b/Packages/NB_FX/.git.backup/objects/4d/56db7248df5a109716fe14e491ab0191aa3734 new file mode 100644 index 00000000..3f1df6e7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4d/56db7248df5a109716fe14e491ab0191aa3734 differ diff --git a/Packages/NB_FX/.git.backup/objects/4d/b4992dfa69bd409b73d6394a45ce521b75d788 b/Packages/NB_FX/.git.backup/objects/4d/b4992dfa69bd409b73d6394a45ce521b75d788 new file mode 100644 index 00000000..141ad057 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4d/b4992dfa69bd409b73d6394a45ce521b75d788 differ diff --git a/Packages/NB_FX/.git.backup/objects/4d/c93de5b6751599464add167d63d386f77261ba b/Packages/NB_FX/.git.backup/objects/4d/c93de5b6751599464add167d63d386f77261ba new file mode 100644 index 00000000..cdb9734c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4d/c93de5b6751599464add167d63d386f77261ba differ diff --git a/Packages/NB_FX/.git.backup/objects/4e/0caa644c06e917ef3d752f5d98e06a32155290 b/Packages/NB_FX/.git.backup/objects/4e/0caa644c06e917ef3d752f5d98e06a32155290 new file mode 100644 index 00000000..bedf82c9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4e/0caa644c06e917ef3d752f5d98e06a32155290 differ diff --git a/Packages/NB_FX/.git.backup/objects/4e/6adcb3850a78bb599ed3c0cedda67a1a283312 b/Packages/NB_FX/.git.backup/objects/4e/6adcb3850a78bb599ed3c0cedda67a1a283312 new file mode 100644 index 00000000..07862b85 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/4e/6adcb3850a78bb599ed3c0cedda67a1a283312 @@ -0,0 +1,3 @@ +x+)JMU017e040031QK,L/JePHFNO^{TS@~qI@Q~rjqqf^^njI"{T=Yޯl\M @]=Ch/'ڹw/\8C\nvpFbJjQ1=|8%!tQ}aB2(ah3Uئ27!ԐmA3K|Fxv` \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/4e/e642ef40130ff443f26c7c9fd8ebcc4e063314 b/Packages/NB_FX/.git.backup/objects/4e/e642ef40130ff443f26c7c9fd8ebcc4e063314 new file mode 100644 index 00000000..11a4b830 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4e/e642ef40130ff443f26c7c9fd8ebcc4e063314 differ diff --git a/Packages/NB_FX/.git.backup/objects/4f/1b62bbd2bc6b0f84cbb59052ca8e2dc6613297 b/Packages/NB_FX/.git.backup/objects/4f/1b62bbd2bc6b0f84cbb59052ca8e2dc6613297 new file mode 100644 index 00000000..174561ea Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4f/1b62bbd2bc6b0f84cbb59052ca8e2dc6613297 differ diff --git a/Packages/NB_FX/.git.backup/objects/4f/7e080b1418c07a0338c1204f3f9b2ae5e24073 b/Packages/NB_FX/.git.backup/objects/4f/7e080b1418c07a0338c1204f3f9b2ae5e24073 new file mode 100644 index 00000000..8b1306f6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/4f/7e080b1418c07a0338c1204f3f9b2ae5e24073 differ diff --git a/Packages/NB_FX/.git.backup/objects/50/210a996a2ba04c0cb77defb3659bbde454623a b/Packages/NB_FX/.git.backup/objects/50/210a996a2ba04c0cb77defb3659bbde454623a new file mode 100644 index 00000000..80ca13db Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/50/210a996a2ba04c0cb77defb3659bbde454623a differ diff --git a/Packages/NB_FX/.git.backup/objects/51/39b264333b4cee5af3bae17a89624487b09dd8 b/Packages/NB_FX/.git.backup/objects/51/39b264333b4cee5af3bae17a89624487b09dd8 new file mode 100644 index 00000000..16318dc6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/51/39b264333b4cee5af3bae17a89624487b09dd8 differ diff --git a/Packages/NB_FX/.git.backup/objects/52/a1211b1a8b81771926a3ed68e1ec787628c989 b/Packages/NB_FX/.git.backup/objects/52/a1211b1a8b81771926a3ed68e1ec787628c989 new file mode 100644 index 00000000..95bd5ff3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/52/a1211b1a8b81771926a3ed68e1ec787628c989 differ diff --git a/Packages/NB_FX/.git.backup/objects/52/d064660eee08f9367ecf47dc5ca64d14be392a b/Packages/NB_FX/.git.backup/objects/52/d064660eee08f9367ecf47dc5ca64d14be392a new file mode 100644 index 00000000..4f4e7d85 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/52/d064660eee08f9367ecf47dc5ca64d14be392a differ diff --git a/Packages/NB_FX/.git.backup/objects/53/10a0d6a5606e78977871b9f8da4bbdfde5511f b/Packages/NB_FX/.git.backup/objects/53/10a0d6a5606e78977871b9f8da4bbdfde5511f new file mode 100644 index 00000000..d19e311e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/53/10a0d6a5606e78977871b9f8da4bbdfde5511f differ diff --git a/Packages/NB_FX/.git.backup/objects/53/65f4b3745e99163eaff6be8367f372a5c440cc b/Packages/NB_FX/.git.backup/objects/53/65f4b3745e99163eaff6be8367f372a5c440cc new file mode 100644 index 00000000..ab955878 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/53/65f4b3745e99163eaff6be8367f372a5c440cc differ diff --git a/Packages/NB_FX/.git.backup/objects/53/a0f59afc7bdf8dfd24649de71b6fbae626bc50 b/Packages/NB_FX/.git.backup/objects/53/a0f59afc7bdf8dfd24649de71b6fbae626bc50 new file mode 100644 index 00000000..d59d798f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/53/a0f59afc7bdf8dfd24649de71b6fbae626bc50 differ diff --git a/Packages/NB_FX/.git.backup/objects/54/037dc2f98ee8a5c6fb95e87b3304ee9f426148 b/Packages/NB_FX/.git.backup/objects/54/037dc2f98ee8a5c6fb95e87b3304ee9f426148 new file mode 100644 index 00000000..e075258d --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/54/037dc2f98ee8a5c6fb95e87b3304ee9f426148 @@ -0,0 +1,2 @@ +xOK0=SЋu' +la)iIIRF6M\$yr?i4%l3m J&pIfj9*r ЍI9@j)TkWWjj|`7O'ߡBցxmx?%,hc364J vU5,\#jEˊž*a3MS0[?`3*>2j#4EΊz$)ߔw!Ӱ<83Qɑ̩ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/54/facd4576a35115e583423160ba41e7fa63bcaa b/Packages/NB_FX/.git.backup/objects/54/facd4576a35115e583423160ba41e7fa63bcaa new file mode 100644 index 00000000..1d549a3b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/54/facd4576a35115e583423160ba41e7fa63bcaa differ diff --git a/Packages/NB_FX/.git.backup/objects/55/8f8d079ae4b2870bbba459acf57368171f7e09 b/Packages/NB_FX/.git.backup/objects/55/8f8d079ae4b2870bbba459acf57368171f7e09 new file mode 100644 index 00000000..20a0ddfa Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/55/8f8d079ae4b2870bbba459acf57368171f7e09 differ diff --git a/Packages/NB_FX/.git.backup/objects/56/389cc8d180a9e9f35c8bdc1e47b0ccb7070d8e b/Packages/NB_FX/.git.backup/objects/56/389cc8d180a9e9f35c8bdc1e47b0ccb7070d8e new file mode 100644 index 00000000..55d91e1d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/56/389cc8d180a9e9f35c8bdc1e47b0ccb7070d8e differ diff --git a/Packages/NB_FX/.git.backup/objects/56/6d1dcf1b703e84469483e607611267189dc11a b/Packages/NB_FX/.git.backup/objects/56/6d1dcf1b703e84469483e607611267189dc11a new file mode 100644 index 00000000..c1539294 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/56/6d1dcf1b703e84469483e607611267189dc11a differ diff --git a/Packages/NB_FX/.git.backup/objects/56/a7888ca9cd1a5c0d0e0e98db69e6fe50577024 b/Packages/NB_FX/.git.backup/objects/56/a7888ca9cd1a5c0d0e0e98db69e6fe50577024 new file mode 100644 index 00000000..292e516d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/56/a7888ca9cd1a5c0d0e0e98db69e6fe50577024 differ diff --git a/Packages/NB_FX/.git.backup/objects/56/c7180924951b0c3061723451c327212f6b5b3f b/Packages/NB_FX/.git.backup/objects/56/c7180924951b0c3061723451c327212f6b5b3f new file mode 100644 index 00000000..886a54be Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/56/c7180924951b0c3061723451c327212f6b5b3f differ diff --git a/Packages/NB_FX/.git.backup/objects/56/fd59ae4b687d04b9e217a767c0eff6cf7c90b4 b/Packages/NB_FX/.git.backup/objects/56/fd59ae4b687d04b9e217a767c0eff6cf7c90b4 new file mode 100644 index 00000000..c6408689 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/56/fd59ae4b687d04b9e217a767c0eff6cf7c90b4 differ diff --git a/Packages/NB_FX/.git.backup/objects/57/01f7b7fbe249e87b6721b8a036edc54ac20974 b/Packages/NB_FX/.git.backup/objects/57/01f7b7fbe249e87b6721b8a036edc54ac20974 new file mode 100644 index 00000000..4f646869 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/57/01f7b7fbe249e87b6721b8a036edc54ac20974 differ diff --git a/Packages/NB_FX/.git.backup/objects/57/e527f43b3c8b1c7fddeb6427ceb5bb08c6a097 b/Packages/NB_FX/.git.backup/objects/57/e527f43b3c8b1c7fddeb6427ceb5bb08c6a097 new file mode 100644 index 00000000..966940b7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/57/e527f43b3c8b1c7fddeb6427ceb5bb08c6a097 differ diff --git a/Packages/NB_FX/.git.backup/objects/58/0e08c4f167d4170f60ea489b2b2d7b77d810ea b/Packages/NB_FX/.git.backup/objects/58/0e08c4f167d4170f60ea489b2b2d7b77d810ea new file mode 100644 index 00000000..86667db6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/58/0e08c4f167d4170f60ea489b2b2d7b77d810ea differ diff --git a/Packages/NB_FX/.git.backup/objects/58/2e18748d19f289568451efe701174f527d7f04 b/Packages/NB_FX/.git.backup/objects/58/2e18748d19f289568451efe701174f527d7f04 new file mode 100644 index 00000000..444415e9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/58/2e18748d19f289568451efe701174f527d7f04 differ diff --git a/Packages/NB_FX/.git.backup/objects/58/304b978a9870414feae956620f2e798a761d07 b/Packages/NB_FX/.git.backup/objects/58/304b978a9870414feae956620f2e798a761d07 new file mode 100644 index 00000000..00837152 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/58/304b978a9870414feae956620f2e798a761d07 differ diff --git a/Packages/NB_FX/.git.backup/objects/58/6de395cc7fcac5b54b7862e05ad4d97c72d766 b/Packages/NB_FX/.git.backup/objects/58/6de395cc7fcac5b54b7862e05ad4d97c72d766 new file mode 100644 index 00000000..6dee197f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/58/6de395cc7fcac5b54b7862e05ad4d97c72d766 differ diff --git a/Packages/NB_FX/.git.backup/objects/58/7f1671766a3a518dac20ffc03b33ba697baa3d b/Packages/NB_FX/.git.backup/objects/58/7f1671766a3a518dac20ffc03b33ba697baa3d new file mode 100644 index 00000000..79a33df8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/58/7f1671766a3a518dac20ffc03b33ba697baa3d differ diff --git a/Packages/NB_FX/.git.backup/objects/58/8c2798d8dfd0fbf5def33ab89b31b8945c4d2f b/Packages/NB_FX/.git.backup/objects/58/8c2798d8dfd0fbf5def33ab89b31b8945c4d2f new file mode 100644 index 00000000..51e63e2b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/58/8c2798d8dfd0fbf5def33ab89b31b8945c4d2f differ diff --git a/Packages/NB_FX/.git.backup/objects/58/9f0d231777282c3547260bc4ec8a3b2ddfaa36 b/Packages/NB_FX/.git.backup/objects/58/9f0d231777282c3547260bc4ec8a3b2ddfaa36 new file mode 100644 index 00000000..b1e37875 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/58/9f0d231777282c3547260bc4ec8a3b2ddfaa36 differ diff --git a/Packages/NB_FX/.git.backup/objects/59/9d343fc5ffa2ca1022c96c8c61485acbd837b1 b/Packages/NB_FX/.git.backup/objects/59/9d343fc5ffa2ca1022c96c8c61485acbd837b1 new file mode 100644 index 00000000..29e28f7b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/59/9d343fc5ffa2ca1022c96c8c61485acbd837b1 differ diff --git a/Packages/NB_FX/.git.backup/objects/5b/61ae5b1aceec635022f773dc54e3ebc1bd6995 b/Packages/NB_FX/.git.backup/objects/5b/61ae5b1aceec635022f773dc54e3ebc1bd6995 new file mode 100644 index 00000000..da0ff5d8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5b/61ae5b1aceec635022f773dc54e3ebc1bd6995 differ diff --git a/Packages/NB_FX/.git.backup/objects/5b/a934f99a9e668c8d536facedb171f3a0b9980b b/Packages/NB_FX/.git.backup/objects/5b/a934f99a9e668c8d536facedb171f3a0b9980b new file mode 100644 index 00000000..d60c27eb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5b/a934f99a9e668c8d536facedb171f3a0b9980b differ diff --git a/Packages/NB_FX/.git.backup/objects/5c/3c16a1cbe287c54534a89daa6f493ef8920cbe b/Packages/NB_FX/.git.backup/objects/5c/3c16a1cbe287c54534a89daa6f493ef8920cbe new file mode 100644 index 00000000..198048e6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5c/3c16a1cbe287c54534a89daa6f493ef8920cbe differ diff --git a/Packages/NB_FX/.git.backup/objects/5c/439a7a6c9fb94e32b54f7f17f9847646fa2aa2 b/Packages/NB_FX/.git.backup/objects/5c/439a7a6c9fb94e32b54f7f17f9847646fa2aa2 new file mode 100644 index 00000000..4d400bd3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5c/439a7a6c9fb94e32b54f7f17f9847646fa2aa2 differ diff --git a/Packages/NB_FX/.git.backup/objects/5c/88babb83f3009c05e387503185108565a25cba b/Packages/NB_FX/.git.backup/objects/5c/88babb83f3009c05e387503185108565a25cba new file mode 100644 index 00000000..ebfb65f5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5c/88babb83f3009c05e387503185108565a25cba differ diff --git a/Packages/NB_FX/.git.backup/objects/5c/dd280eeb22f5ed983392560917c34793f357e8 b/Packages/NB_FX/.git.backup/objects/5c/dd280eeb22f5ed983392560917c34793f357e8 new file mode 100644 index 00000000..2a8fbc88 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5c/dd280eeb22f5ed983392560917c34793f357e8 differ diff --git a/Packages/NB_FX/.git.backup/objects/5c/e4b30534731083a330e96b491830bc150e0b05 b/Packages/NB_FX/.git.backup/objects/5c/e4b30534731083a330e96b491830bc150e0b05 new file mode 100644 index 00000000..d663df91 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5c/e4b30534731083a330e96b491830bc150e0b05 differ diff --git a/Packages/NB_FX/.git.backup/objects/5d/eacac3841dce8f8e8550b861c9b130df7e7b92 b/Packages/NB_FX/.git.backup/objects/5d/eacac3841dce8f8e8550b861c9b130df7e7b92 new file mode 100644 index 00000000..1720cc36 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5d/eacac3841dce8f8e8550b861c9b130df7e7b92 differ diff --git a/Packages/NB_FX/.git.backup/objects/5d/ed4ec00a5f8babde54a2631369839380e471f3 b/Packages/NB_FX/.git.backup/objects/5d/ed4ec00a5f8babde54a2631369839380e471f3 new file mode 100644 index 00000000..b1693fae --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/5d/ed4ec00a5f8babde54a2631369839380e471f3 @@ -0,0 +1,2 @@ +xAj0E)f_03gdA)4.7 E2種Py.V{~pƅFè[TFI{^Th"&<^d@VFEV +-.ǭ^RsbN(kkWߢ.t=<~v|?F \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/5e/d2594baca89078b182478a718a74e761d67318 b/Packages/NB_FX/.git.backup/objects/5e/d2594baca89078b182478a718a74e761d67318 new file mode 100644 index 00000000..14ca0fbb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5e/d2594baca89078b182478a718a74e761d67318 differ diff --git a/Packages/NB_FX/.git.backup/objects/5f/0efaecbca96c921f67af26b5df5a3636acb20e b/Packages/NB_FX/.git.backup/objects/5f/0efaecbca96c921f67af26b5df5a3636acb20e new file mode 100644 index 00000000..c7549f23 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5f/0efaecbca96c921f67af26b5df5a3636acb20e differ diff --git a/Packages/NB_FX/.git.backup/objects/5f/15c741cd1f2edbe479afab94fb4162b9ad2a69 b/Packages/NB_FX/.git.backup/objects/5f/15c741cd1f2edbe479afab94fb4162b9ad2a69 new file mode 100644 index 00000000..c05c4556 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5f/15c741cd1f2edbe479afab94fb4162b9ad2a69 differ diff --git a/Packages/NB_FX/.git.backup/objects/5f/3ad2b98400c72ea363961eb19660b0be7a2374 b/Packages/NB_FX/.git.backup/objects/5f/3ad2b98400c72ea363961eb19660b0be7a2374 new file mode 100644 index 00000000..f11b1352 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5f/3ad2b98400c72ea363961eb19660b0be7a2374 differ diff --git a/Packages/NB_FX/.git.backup/objects/5f/8aeabe49d99f5e27e2ea6cf80d0f8a6c6ba8f5 b/Packages/NB_FX/.git.backup/objects/5f/8aeabe49d99f5e27e2ea6cf80d0f8a6c6ba8f5 new file mode 100644 index 00000000..e626c0bf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5f/8aeabe49d99f5e27e2ea6cf80d0f8a6c6ba8f5 differ diff --git a/Packages/NB_FX/.git.backup/objects/5f/e16b085c645abab92cd170127d2876e1ea84f3 b/Packages/NB_FX/.git.backup/objects/5f/e16b085c645abab92cd170127d2876e1ea84f3 new file mode 100644 index 00000000..599be292 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/5f/e16b085c645abab92cd170127d2876e1ea84f3 differ diff --git a/Packages/NB_FX/.git.backup/objects/60/1defc162f4852c0c6de77cf089790b710356ed b/Packages/NB_FX/.git.backup/objects/60/1defc162f4852c0c6de77cf089790b710356ed new file mode 100644 index 00000000..8006e379 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/60/1defc162f4852c0c6de77cf089790b710356ed differ diff --git a/Packages/NB_FX/.git.backup/objects/60/26007f9b9c0a18e42df91177a053b176d63958 b/Packages/NB_FX/.git.backup/objects/60/26007f9b9c0a18e42df91177a053b176d63958 new file mode 100644 index 00000000..40a290b3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/60/26007f9b9c0a18e42df91177a053b176d63958 differ diff --git a/Packages/NB_FX/.git.backup/objects/60/9e8e2684718772d8b4e66b2d051eea2bb321ac b/Packages/NB_FX/.git.backup/objects/60/9e8e2684718772d8b4e66b2d051eea2bb321ac new file mode 100644 index 00000000..5783f8ec Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/60/9e8e2684718772d8b4e66b2d051eea2bb321ac differ diff --git a/Packages/NB_FX/.git.backup/objects/61/0304c607b1245c3c3a4305364ad84a2df45098 b/Packages/NB_FX/.git.backup/objects/61/0304c607b1245c3c3a4305364ad84a2df45098 new file mode 100644 index 00000000..3f51c7d1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/61/0304c607b1245c3c3a4305364ad84a2df45098 differ diff --git a/Packages/NB_FX/.git.backup/objects/61/16ffca0a67b17789db836738ea06357214c558 b/Packages/NB_FX/.git.backup/objects/61/16ffca0a67b17789db836738ea06357214c558 new file mode 100644 index 00000000..41160dce Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/61/16ffca0a67b17789db836738ea06357214c558 differ diff --git a/Packages/NB_FX/.git.backup/objects/61/4191f1655dff1cda348dc0741cbd41bebe1695 b/Packages/NB_FX/.git.backup/objects/61/4191f1655dff1cda348dc0741cbd41bebe1695 new file mode 100644 index 00000000..393b2fcb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/61/4191f1655dff1cda348dc0741cbd41bebe1695 differ diff --git a/Packages/NB_FX/.git.backup/objects/61/bcb59b50888b0326a0e96d90819a02b192db43 b/Packages/NB_FX/.git.backup/objects/61/bcb59b50888b0326a0e96d90819a02b192db43 new file mode 100644 index 00000000..59af2ba2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/61/bcb59b50888b0326a0e96d90819a02b192db43 differ diff --git a/Packages/NB_FX/.git.backup/objects/61/c1bc4363b36e865ed0750ddaf2dcfb95afa7e6 b/Packages/NB_FX/.git.backup/objects/61/c1bc4363b36e865ed0750ddaf2dcfb95afa7e6 new file mode 100644 index 00000000..02725771 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/61/c1bc4363b36e865ed0750ddaf2dcfb95afa7e6 differ diff --git a/Packages/NB_FX/.git.backup/objects/61/cae80023c55f23325131ad70dd025cdcc57279 b/Packages/NB_FX/.git.backup/objects/61/cae80023c55f23325131ad70dd025cdcc57279 new file mode 100644 index 00000000..793b2d9d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/61/cae80023c55f23325131ad70dd025cdcc57279 differ diff --git a/Packages/NB_FX/.git.backup/objects/61/f51aa5aa809dd26e541a68122bcf6ea391ca3d b/Packages/NB_FX/.git.backup/objects/61/f51aa5aa809dd26e541a68122bcf6ea391ca3d new file mode 100644 index 00000000..5c825a92 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/61/f51aa5aa809dd26e541a68122bcf6ea391ca3d differ diff --git a/Packages/NB_FX/.git.backup/objects/62/4585b87dc07b5de79a2f74e51a5775a83c7dcf b/Packages/NB_FX/.git.backup/objects/62/4585b87dc07b5de79a2f74e51a5775a83c7dcf new file mode 100644 index 00000000..36fc7b8a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/62/4585b87dc07b5de79a2f74e51a5775a83c7dcf differ diff --git a/Packages/NB_FX/.git.backup/objects/62/92e5cb55b63a5438725b4818737e0a46e57b48 b/Packages/NB_FX/.git.backup/objects/62/92e5cb55b63a5438725b4818737e0a46e57b48 new file mode 100644 index 00000000..6aff84d9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/62/92e5cb55b63a5438725b4818737e0a46e57b48 differ diff --git a/Packages/NB_FX/.git.backup/objects/63/b8dc5a780fef714d3ee5dc7cb4e82db7e1a303 b/Packages/NB_FX/.git.backup/objects/63/b8dc5a780fef714d3ee5dc7cb4e82db7e1a303 new file mode 100644 index 00000000..bbbab9b4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/63/b8dc5a780fef714d3ee5dc7cb4e82db7e1a303 differ diff --git a/Packages/NB_FX/.git.backup/objects/63/e82f60b7f83a20ff7736596d2892e14fb50cf9 b/Packages/NB_FX/.git.backup/objects/63/e82f60b7f83a20ff7736596d2892e14fb50cf9 new file mode 100644 index 00000000..cea61f75 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/63/e82f60b7f83a20ff7736596d2892e14fb50cf9 @@ -0,0 +1 @@ +x 1=yKdV_Wpw5 &ogy<RCNWΒ#?-d2+1Voxܘ [Ny|P@=|jzSZQpsIқ9ZZ) u 6~qcKV\;/ώ3RS|*S_ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/64/9d567c5c9b5b8d2197c2e49c76c9828e3b7c77 b/Packages/NB_FX/.git.backup/objects/64/9d567c5c9b5b8d2197c2e49c76c9828e3b7c77 new file mode 100644 index 00000000..8718ef19 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/64/9d567c5c9b5b8d2197c2e49c76c9828e3b7c77 differ diff --git a/Packages/NB_FX/.git.backup/objects/64/a0a0b462e712f3a55839cb070ab635fac1e3e2 b/Packages/NB_FX/.git.backup/objects/64/a0a0b462e712f3a55839cb070ab635fac1e3e2 new file mode 100644 index 00000000..129f6e71 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/64/a0a0b462e712f3a55839cb070ab635fac1e3e2 differ diff --git a/Packages/NB_FX/.git.backup/objects/65/f0a0fa5c30f77c884fe0b6b1ac0988ad50fbec b/Packages/NB_FX/.git.backup/objects/65/f0a0fa5c30f77c884fe0b6b1ac0988ad50fbec new file mode 100644 index 00000000..61d4d068 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/65/f0a0fa5c30f77c884fe0b6b1ac0988ad50fbec @@ -0,0 +1,3 @@ +x]j1DSW't&QLEbH&X悌N + +M=kW!cx;.fGrD!'KCقz6\L`cf?#n&ל~EPlGo=ǃ;cj-;Z8%C񪥍0v]CZM;k<#xvdD/pRx \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/66/7f908b1210ddd2c8eaec088c8ee92146baa661 b/Packages/NB_FX/.git.backup/objects/66/7f908b1210ddd2c8eaec088c8ee92146baa661 new file mode 100644 index 00000000..a41bdfdf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/66/7f908b1210ddd2c8eaec088c8ee92146baa661 differ diff --git a/Packages/NB_FX/.git.backup/objects/66/c3a6564a80d55e1bb08da544d88ffc32bacc7c b/Packages/NB_FX/.git.backup/objects/66/c3a6564a80d55e1bb08da544d88ffc32bacc7c new file mode 100644 index 00000000..98198dc4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/66/c3a6564a80d55e1bb08da544d88ffc32bacc7c differ diff --git a/Packages/NB_FX/.git.backup/objects/66/fdf2e46e7fce95264c99317bf82eb8685a7d7b b/Packages/NB_FX/.git.backup/objects/66/fdf2e46e7fce95264c99317bf82eb8685a7d7b new file mode 100644 index 00000000..c1f870b9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/66/fdf2e46e7fce95264c99317bf82eb8685a7d7b differ diff --git a/Packages/NB_FX/.git.backup/objects/67/3eed215f80797645a8e239de9bcd119916cc57 b/Packages/NB_FX/.git.backup/objects/67/3eed215f80797645a8e239de9bcd119916cc57 new file mode 100644 index 00000000..fc70e8f5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/67/3eed215f80797645a8e239de9bcd119916cc57 differ diff --git a/Packages/NB_FX/.git.backup/objects/67/623e48121bbbe3fd96396080834e3f6dad3cac b/Packages/NB_FX/.git.backup/objects/67/623e48121bbbe3fd96396080834e3f6dad3cac new file mode 100644 index 00000000..5b1d3744 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/67/623e48121bbbe3fd96396080834e3f6dad3cac differ diff --git a/Packages/NB_FX/.git.backup/objects/67/d0a35ea436a20537831ef0c1cc6f0e0597676f b/Packages/NB_FX/.git.backup/objects/67/d0a35ea436a20537831ef0c1cc6f0e0597676f new file mode 100644 index 00000000..f0867453 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/67/d0a35ea436a20537831ef0c1cc6f0e0597676f differ diff --git a/Packages/NB_FX/.git.backup/objects/68/44e99a7ed3c0da9f9515c535dc5e7ffe8553cf b/Packages/NB_FX/.git.backup/objects/68/44e99a7ed3c0da9f9515c535dc5e7ffe8553cf new file mode 100644 index 00000000..6e61f9a5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/68/44e99a7ed3c0da9f9515c535dc5e7ffe8553cf differ diff --git a/Packages/NB_FX/.git.backup/objects/68/b8f78af4eca5ca38a85b36532b5984ef3f5f47 b/Packages/NB_FX/.git.backup/objects/68/b8f78af4eca5ca38a85b36532b5984ef3f5f47 new file mode 100644 index 00000000..d81922be Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/68/b8f78af4eca5ca38a85b36532b5984ef3f5f47 differ diff --git a/Packages/NB_FX/.git.backup/objects/69/531453bc2f8c1b96d2178deadc26df38c641c5 b/Packages/NB_FX/.git.backup/objects/69/531453bc2f8c1b96d2178deadc26df38c641c5 new file mode 100644 index 00000000..be4cdfb8 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/69/531453bc2f8c1b96d2178deadc26df38c641c5 @@ -0,0 +1,2 @@ +x; +1E1?q+/-1kp֊..sNlz%YʦtڒLƌ25<љc**ʑa  S i宣văR6QlkB-ȡrJbK^濏u>.{ގoKj \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/69/b8967a4027cfb7c5f56b7984b9e19dfb20e94a b/Packages/NB_FX/.git.backup/objects/69/b8967a4027cfb7c5f56b7984b9e19dfb20e94a new file mode 100644 index 00000000..775d3de9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/69/b8967a4027cfb7c5f56b7984b9e19dfb20e94a differ diff --git a/Packages/NB_FX/.git.backup/objects/69/b8a1ecda8168b6d3cc8e021fb459f06685154b b/Packages/NB_FX/.git.backup/objects/69/b8a1ecda8168b6d3cc8e021fb459f06685154b new file mode 100644 index 00000000..dfd46297 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/69/b8a1ecda8168b6d3cc8e021fb459f06685154b differ diff --git a/Packages/NB_FX/.git.backup/objects/6a/091357f04194993c22fa6048aa88a8d0ef847b b/Packages/NB_FX/.git.backup/objects/6a/091357f04194993c22fa6048aa88a8d0ef847b new file mode 100644 index 00000000..60379bcd Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6a/091357f04194993c22fa6048aa88a8d0ef847b differ diff --git a/Packages/NB_FX/.git.backup/objects/6a/0e3b3be00c8833ef4a7fbc75d25e477606e19f b/Packages/NB_FX/.git.backup/objects/6a/0e3b3be00c8833ef4a7fbc75d25e477606e19f new file mode 100644 index 00000000..a9b570a2 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/6a/0e3b3be00c8833ef4a7fbc75d25e477606e19f @@ -0,0 +1,2 @@ +x]j1SS#UpaR )QPIF?`lY +v>ogy&|xevB!'CjcլԤrگ7~/j9rΥ9 ۪]hE "=wx$ |J`{!DK`n!Rm?][nlH׊ړ82#5?1R2 \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/6a/276401a818c135eb2a94aa040d032c3556935a b/Packages/NB_FX/.git.backup/objects/6a/276401a818c135eb2a94aa040d032c3556935a new file mode 100644 index 00000000..f9511fab Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6a/276401a818c135eb2a94aa040d032c3556935a differ diff --git a/Packages/NB_FX/.git.backup/objects/6a/417787e1a833922a78d8af7b0137e1b90389d6 b/Packages/NB_FX/.git.backup/objects/6a/417787e1a833922a78d8af7b0137e1b90389d6 new file mode 100644 index 00000000..c6110965 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/6a/417787e1a833922a78d8af7b0137e1b90389d6 @@ -0,0 +1,2 @@ +xR=O0d@U)C,@U NT,9!wc7TXh6YpBi;mAi*[X ΰ-fk.`>XWPLh(NU +#1ѣZ8VKG,ޮ r`BOJh"JYqpulO5979Sw79ء# +&0*ʤ<ءWJbӛSsғ+5bQZ/iB2O_ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/6a/5dfa0b77bde6dd4ab800a9c5ba66949faa265b b/Packages/NB_FX/.git.backup/objects/6a/5dfa0b77bde6dd4ab800a9c5ba66949faa265b new file mode 100644 index 00000000..40e3ac34 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6a/5dfa0b77bde6dd4ab800a9c5ba66949faa265b differ diff --git a/Packages/NB_FX/.git.backup/objects/6a/6658be690e90d7b2058b6e60573da797b59709 b/Packages/NB_FX/.git.backup/objects/6a/6658be690e90d7b2058b6e60573da797b59709 new file mode 100644 index 00000000..a635a1ef Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6a/6658be690e90d7b2058b6e60573da797b59709 differ diff --git a/Packages/NB_FX/.git.backup/objects/6b/cc7397c85c50d838bbbeec349276f7b61bf268 b/Packages/NB_FX/.git.backup/objects/6b/cc7397c85c50d838bbbeec349276f7b61bf268 new file mode 100644 index 00000000..96c8789a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6b/cc7397c85c50d838bbbeec349276f7b61bf268 differ diff --git a/Packages/NB_FX/.git.backup/objects/6b/fa71dc60940f0739cec77bc5d09face73711aa b/Packages/NB_FX/.git.backup/objects/6b/fa71dc60940f0739cec77bc5d09face73711aa new file mode 100644 index 00000000..3cbe26ee Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6b/fa71dc60940f0739cec77bc5d09face73711aa differ diff --git a/Packages/NB_FX/.git.backup/objects/6c/023562f809110863b2e6e8aaf05ea749fa4d34 b/Packages/NB_FX/.git.backup/objects/6c/023562f809110863b2e6e8aaf05ea749fa4d34 new file mode 100644 index 00000000..67ec4004 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/6c/023562f809110863b2e6e8aaf05ea749fa4d34 @@ -0,0 +1,2 @@ +x]N0D 'KtBNQl 2rld%ĉg +<BfnrF!'K{k[4oga?wc̰cN}"(#§iyj򭴢 "[g(HZy5!UK;e]w]BZ=_Mkܷ#xvfDQ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/6c/c9f424f6777acf2c7dec3fa838e3e963874d03 b/Packages/NB_FX/.git.backup/objects/6c/c9f424f6777acf2c7dec3fa838e3e963874d03 new file mode 100644 index 00000000..df00622d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6c/c9f424f6777acf2c7dec3fa838e3e963874d03 differ diff --git a/Packages/NB_FX/.git.backup/objects/6d/06c28d444e97e07375dfa0c2e363cea839cdae b/Packages/NB_FX/.git.backup/objects/6d/06c28d444e97e07375dfa0c2e363cea839cdae new file mode 100644 index 00000000..c0fa470e --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/6d/06c28d444e97e07375dfa0c2e363cea839cdae @@ -0,0 +1,2 @@ +x+)JMU02`040031QpM,/M-IdX.t ^?^z|a}Q bYzoP?o2|~39Ay%>۫ m~=,f_ίondR"]?! jRpFbJ*EY2s2dq *vci +W,̝7Y \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/6d/ca94b0ebf640a1429b092172a98c8fbc385f95 b/Packages/NB_FX/.git.backup/objects/6d/ca94b0ebf640a1429b092172a98c8fbc385f95 new file mode 100644 index 00000000..0f4c2b4a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6d/ca94b0ebf640a1429b092172a98c8fbc385f95 differ diff --git a/Packages/NB_FX/.git.backup/objects/6e/1d3add4cff186196f26c55f8fcb7e457a83612 b/Packages/NB_FX/.git.backup/objects/6e/1d3add4cff186196f26c55f8fcb7e457a83612 new file mode 100644 index 00000000..dcbd7965 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6e/1d3add4cff186196f26c55f8fcb7e457a83612 differ diff --git a/Packages/NB_FX/.git.backup/objects/6e/ef855663d5b07177e579b2b07773b961d19404 b/Packages/NB_FX/.git.backup/objects/6e/ef855663d5b07177e579b2b07773b961d19404 new file mode 100644 index 00000000..7cddf10d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6e/ef855663d5b07177e579b2b07773b961d19404 differ diff --git a/Packages/NB_FX/.git.backup/objects/6e/f882ce4264c63fa9e349464d75329b2a074a2b b/Packages/NB_FX/.git.backup/objects/6e/f882ce4264c63fa9e349464d75329b2a074a2b new file mode 100644 index 00000000..1059551e --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/6e/f882ce4264c63fa9e349464d75329b2a074a2b @@ -0,0 +1,2 @@ +xAJ@D])z/ UO7"'KF&g#zq5.]i\y@ţ +JꪺjuFIۄpf [&$(: R91F.uфeeĈDYȡ78e$ADE蛮X,} MՙՅ6̘\Jq׏c6yzzkS d \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/6f/1903a4f0668bf99883ef778ad00a616b25bac6 b/Packages/NB_FX/.git.backup/objects/6f/1903a4f0668bf99883ef778ad00a616b25bac6 new file mode 100644 index 00000000..3d3b9832 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6f/1903a4f0668bf99883ef778ad00a616b25bac6 differ diff --git a/Packages/NB_FX/.git.backup/objects/6f/25c92bb04ff3c54440811414e7e8b5fe64f320 b/Packages/NB_FX/.git.backup/objects/6f/25c92bb04ff3c54440811414e7e8b5fe64f320 new file mode 100644 index 00000000..d26751cc --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/6f/25c92bb04ff3c54440811414e7e8b5fe64f320 @@ -0,0 +1,3 @@ +xA +0D] %7MR*/u@/FpFT<, 3o}nGfY32x|t0aǦRN%q( +ot*U>U6:4ŦiLIrSR6!}`M҄\P"t/EYi^>r{. %I \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/6f/6cd01fbc868c5448ed314e757de46800d6b25b b/Packages/NB_FX/.git.backup/objects/6f/6cd01fbc868c5448ed314e757de46800d6b25b new file mode 100644 index 00000000..3d062fc1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6f/6cd01fbc868c5448ed314e757de46800d6b25b differ diff --git a/Packages/NB_FX/.git.backup/objects/6f/7bd590985d65adf6181cf7171247d2292a447d b/Packages/NB_FX/.git.backup/objects/6f/7bd590985d65adf6181cf7171247d2292a447d new file mode 100644 index 00000000..4947d4df Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6f/7bd590985d65adf6181cf7171247d2292a447d differ diff --git a/Packages/NB_FX/.git.backup/objects/6f/c8645d61636c147e13ff641a5fd40a9fdd4f8c b/Packages/NB_FX/.git.backup/objects/6f/c8645d61636c147e13ff641a5fd40a9fdd4f8c new file mode 100644 index 00000000..9cefb45f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6f/c8645d61636c147e13ff641a5fd40a9fdd4f8c differ diff --git a/Packages/NB_FX/.git.backup/objects/6f/efabb3ba1373c0a306b14d72b27a0b77751c23 b/Packages/NB_FX/.git.backup/objects/6f/efabb3ba1373c0a306b14d72b27a0b77751c23 new file mode 100644 index 00000000..24c047f9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/6f/efabb3ba1373c0a306b14d72b27a0b77751c23 differ diff --git a/Packages/NB_FX/.git.backup/objects/70/1277dc80cf45c3640d90d829dd57786272161f b/Packages/NB_FX/.git.backup/objects/70/1277dc80cf45c3640d90d829dd57786272161f new file mode 100644 index 00000000..b8285190 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/70/1277dc80cf45c3640d90d829dd57786272161f differ diff --git a/Packages/NB_FX/.git.backup/objects/72/01409c171ecb5ffe7906c4d071523cc965dfb9 b/Packages/NB_FX/.git.backup/objects/72/01409c171ecb5ffe7906c4d071523cc965dfb9 new file mode 100644 index 00000000..de842392 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/72/01409c171ecb5ffe7906c4d071523cc965dfb9 differ diff --git a/Packages/NB_FX/.git.backup/objects/73/0f3c6d9ce6abfa319ead285df0921e0eecef8b b/Packages/NB_FX/.git.backup/objects/73/0f3c6d9ce6abfa319ead285df0921e0eecef8b new file mode 100644 index 00000000..7d183bc5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/73/0f3c6d9ce6abfa319ead285df0921e0eecef8b differ diff --git a/Packages/NB_FX/.git.backup/objects/73/11e99f78178383597cb2306504741b748f9066 b/Packages/NB_FX/.git.backup/objects/73/11e99f78178383597cb2306504741b748f9066 new file mode 100644 index 00000000..57b4737f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/73/11e99f78178383597cb2306504741b748f9066 differ diff --git a/Packages/NB_FX/.git.backup/objects/73/3ffc1c1e17f56ed271964dc8b3e4a626d117c1 b/Packages/NB_FX/.git.backup/objects/73/3ffc1c1e17f56ed271964dc8b3e4a626d117c1 new file mode 100644 index 00000000..cc8b34e3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/73/3ffc1c1e17f56ed271964dc8b3e4a626d117c1 differ diff --git a/Packages/NB_FX/.git.backup/objects/73/72dec681e5f25cba7aa0bfa01056b32e3faa56 b/Packages/NB_FX/.git.backup/objects/73/72dec681e5f25cba7aa0bfa01056b32e3faa56 new file mode 100644 index 00000000..6c4eb64b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/73/72dec681e5f25cba7aa0bfa01056b32e3faa56 differ diff --git a/Packages/NB_FX/.git.backup/objects/73/78e06f07402aa5472dd161c711d59012ddd774 b/Packages/NB_FX/.git.backup/objects/73/78e06f07402aa5472dd161c711d59012ddd774 new file mode 100644 index 00000000..2c274e4d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/73/78e06f07402aa5472dd161c711d59012ddd774 differ diff --git a/Packages/NB_FX/.git.backup/objects/73/7dcd5b2d1b2f57a91b863d4e2a8b2def06b812 b/Packages/NB_FX/.git.backup/objects/73/7dcd5b2d1b2f57a91b863d4e2a8b2def06b812 new file mode 100644 index 00000000..c3a78bc4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/73/7dcd5b2d1b2f57a91b863d4e2a8b2def06b812 differ diff --git a/Packages/NB_FX/.git.backup/objects/73/824b4747f067deb22c3785c00c02ebf4017e80 b/Packages/NB_FX/.git.backup/objects/73/824b4747f067deb22c3785c00c02ebf4017e80 new file mode 100644 index 00000000..142d0361 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/73/824b4747f067deb22c3785c00c02ebf4017e80 differ diff --git a/Packages/NB_FX/.git.backup/objects/73/c5a35b2a102a148a854d81c161de8e1cbb1ce1 b/Packages/NB_FX/.git.backup/objects/73/c5a35b2a102a148a854d81c161de8e1cbb1ce1 new file mode 100644 index 00000000..73f0ec50 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/73/c5a35b2a102a148a854d81c161de8e1cbb1ce1 differ diff --git a/Packages/NB_FX/.git.backup/objects/74/228abf94ca8136fef28a3f08ab591e1e8f736e b/Packages/NB_FX/.git.backup/objects/74/228abf94ca8136fef28a3f08ab591e1e8f736e new file mode 100644 index 00000000..e095d70e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/74/228abf94ca8136fef28a3f08ab591e1e8f736e differ diff --git a/Packages/NB_FX/.git.backup/objects/74/287bd905bfd0d45fb75b077c692a72fc85aa01 b/Packages/NB_FX/.git.backup/objects/74/287bd905bfd0d45fb75b077c692a72fc85aa01 new file mode 100644 index 00000000..8db5f635 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/74/287bd905bfd0d45fb75b077c692a72fc85aa01 differ diff --git a/Packages/NB_FX/.git.backup/objects/74/5ec9bcea40d432fd2b820b03d0f7c35439477c b/Packages/NB_FX/.git.backup/objects/74/5ec9bcea40d432fd2b820b03d0f7c35439477c new file mode 100644 index 00000000..380ef441 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/74/5ec9bcea40d432fd2b820b03d0f7c35439477c differ diff --git a/Packages/NB_FX/.git.backup/objects/74/6b9ca52f8b8aed9c1c23af118a735ee6658f93 b/Packages/NB_FX/.git.backup/objects/74/6b9ca52f8b8aed9c1c23af118a735ee6658f93 new file mode 100644 index 00000000..08844b8b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/74/6b9ca52f8b8aed9c1c23af118a735ee6658f93 differ diff --git a/Packages/NB_FX/.git.backup/objects/75/32321a64f39cd989de86e23ec372476f8875b2 b/Packages/NB_FX/.git.backup/objects/75/32321a64f39cd989de86e23ec372476f8875b2 new file mode 100644 index 00000000..4125ec81 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/75/32321a64f39cd989de86e23ec372476f8875b2 differ diff --git a/Packages/NB_FX/.git.backup/objects/75/7b3c35b78f4081cad334902942b0f90370f603 b/Packages/NB_FX/.git.backup/objects/75/7b3c35b78f4081cad334902942b0f90370f603 new file mode 100644 index 00000000..d8e675f3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/75/7b3c35b78f4081cad334902942b0f90370f603 differ diff --git a/Packages/NB_FX/.git.backup/objects/75/d025b8c3ecec3ae5c6bf1b5dcd0c190219e255 b/Packages/NB_FX/.git.backup/objects/75/d025b8c3ecec3ae5c6bf1b5dcd0c190219e255 new file mode 100644 index 00000000..b4d3b418 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/75/d025b8c3ecec3ae5c6bf1b5dcd0c190219e255 differ diff --git a/Packages/NB_FX/.git.backup/objects/76/202851cc8b314ebb4956e7b4fb4ca84f278308 b/Packages/NB_FX/.git.backup/objects/76/202851cc8b314ebb4956e7b4fb4ca84f278308 new file mode 100644 index 00000000..222deafc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/76/202851cc8b314ebb4956e7b4fb4ca84f278308 differ diff --git a/Packages/NB_FX/.git.backup/objects/76/26833e6ccc75040d5a9156c68f69edf6c3330e b/Packages/NB_FX/.git.backup/objects/76/26833e6ccc75040d5a9156c68f69edf6c3330e new file mode 100644 index 00000000..ff8e6265 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/76/26833e6ccc75040d5a9156c68f69edf6c3330e @@ -0,0 +1,3 @@ +x1 +@E 2c;*3]HbBWR +̓7UJz:5ԅy226cd·šd"8b՚P'-6esH0䂣>-No{7~@vѶTs䀬5z @ vߡWEX5͔$](N_*i9LT)EM[jUAsP`Y&p +)ercFʋVmG(k2T{MƣJѓ֫XܒHsrS8=9EgL_"نp$g t309YJgCϼg68̽ZpqBpvKCXjLucFbTpi&Eky%Udw+ap C8E>ScEZ3U0" _iuS{PmI('EE 'D -+]mSkq4[J̫tMaDj%:Y8g]1 \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/8e/70e8be13f456f7c1f89b815fcaec5d5f7ed87b b/Packages/NB_FX/.git.backup/objects/8e/70e8be13f456f7c1f89b815fcaec5d5f7ed87b new file mode 100644 index 00000000..a4190c5d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/8e/70e8be13f456f7c1f89b815fcaec5d5f7ed87b differ diff --git a/Packages/NB_FX/.git.backup/objects/8e/a1e71280c34f5f5c8c06eb436a696f00dc56ff b/Packages/NB_FX/.git.backup/objects/8e/a1e71280c34f5f5c8c06eb436a696f00dc56ff new file mode 100644 index 00000000..af125148 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/8e/a1e71280c34f5f5c8c06eb436a696f00dc56ff differ diff --git a/Packages/NB_FX/.git.backup/objects/8e/c11c462b493cfd77f4d3376276de4c30eb3ce2 b/Packages/NB_FX/.git.backup/objects/8e/c11c462b493cfd77f4d3376276de4c30eb3ce2 new file mode 100644 index 00000000..e3dfa042 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/8e/c11c462b493cfd77f4d3376276de4c30eb3ce2 differ diff --git a/Packages/NB_FX/.git.backup/objects/8e/e28b7221edf8493ddad1042f46b2bd69bd83ec b/Packages/NB_FX/.git.backup/objects/8e/e28b7221edf8493ddad1042f46b2bd69bd83ec new file mode 100644 index 00000000..7fb7264e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/8e/e28b7221edf8493ddad1042f46b2bd69bd83ec differ diff --git a/Packages/NB_FX/.git.backup/objects/8f/ad4d899a5a66abc299cffc1da03db40635bc30 b/Packages/NB_FX/.git.backup/objects/8f/ad4d899a5a66abc299cffc1da03db40635bc30 new file mode 100644 index 00000000..1bc1f276 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/8f/ad4d899a5a66abc299cffc1da03db40635bc30 @@ -0,0 +1,4 @@ +xUn0Y_12`8hC&AR- )P[#O/Cɢ([Ytyy3 5?~z߲rATIng)7JWr%DdX,A>ue=E` @"XQ@nz|j7Wa5_0J%299Iujm[mK"s%% +p%l4g"rfi(yD&瘾 ^GSP7W7J t}zF}δo<+00oB7MeH`kɄǨNf/jVB/CXW [v~B̥e=_FP̸\gܾ9@nԾ>)YCaՠ^M<h˥~> \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/90/a222deed38c893adac0b0ecdd6a708ee33d85a b/Packages/NB_FX/.git.backup/objects/90/a222deed38c893adac0b0ecdd6a708ee33d85a new file mode 100644 index 00000000..d8e4fccd --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/90/a222deed38c893adac0b0ecdd6a708ee33d85a @@ -0,0 +1,2 @@ +x10 PfNbBJ,SlS(0F +KYI:"(mM.XrBg`! _elt4ètDd: \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/90/cb8c07285c653c0cd3103219276240a96e624c b/Packages/NB_FX/.git.backup/objects/90/cb8c07285c653c0cd3103219276240a96e624c new file mode 100644 index 00000000..a0feb013 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/90/cb8c07285c653c0cd3103219276240a96e624c differ diff --git a/Packages/NB_FX/.git.backup/objects/91/030155e04247bc6802a3a0c09cf533f50b70a2 b/Packages/NB_FX/.git.backup/objects/91/030155e04247bc6802a3a0c09cf533f50b70a2 new file mode 100644 index 00000000..878b631a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/91/030155e04247bc6802a3a0c09cf533f50b70a2 differ diff --git a/Packages/NB_FX/.git.backup/objects/91/7d36c3de925450b594eb21c582d83dc9cd11c8 b/Packages/NB_FX/.git.backup/objects/91/7d36c3de925450b594eb21c582d83dc9cd11c8 new file mode 100644 index 00000000..8d543eac Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/91/7d36c3de925450b594eb21c582d83dc9cd11c8 differ diff --git a/Packages/NB_FX/.git.backup/objects/91/b254db3a3560ea22e1e7d8d0a3bcb321f772ad b/Packages/NB_FX/.git.backup/objects/91/b254db3a3560ea22e1e7d8d0a3bcb321f772ad new file mode 100644 index 00000000..00793676 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/91/b254db3a3560ea22e1e7d8d0a3bcb321f772ad differ diff --git a/Packages/NB_FX/.git.backup/objects/92/787d3bb0bbeabc67fa75fa2265dd50d73d24da b/Packages/NB_FX/.git.backup/objects/92/787d3bb0bbeabc67fa75fa2265dd50d73d24da new file mode 100644 index 00000000..8c4c4b5d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/92/787d3bb0bbeabc67fa75fa2265dd50d73d24da differ diff --git a/Packages/NB_FX/.git.backup/objects/93/1f391b07452be05afc331e9c51a8c6661bd6ea b/Packages/NB_FX/.git.backup/objects/93/1f391b07452be05afc331e9c51a8c6661bd6ea new file mode 100644 index 00000000..696f3646 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/93/1f391b07452be05afc331e9c51a8c6661bd6ea differ diff --git a/Packages/NB_FX/.git.backup/objects/94/0e46bb1c1a4a11bb75da3811b9fd6e4a12bec9 b/Packages/NB_FX/.git.backup/objects/94/0e46bb1c1a4a11bb75da3811b9fd6e4a12bec9 new file mode 100644 index 00000000..da1cf42b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/94/0e46bb1c1a4a11bb75da3811b9fd6e4a12bec9 differ diff --git a/Packages/NB_FX/.git.backup/objects/94/13b9cd46fc6ba8dc4ac6e394508057a224d92d b/Packages/NB_FX/.git.backup/objects/94/13b9cd46fc6ba8dc4ac6e394508057a224d92d new file mode 100644 index 00000000..74099d13 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/94/13b9cd46fc6ba8dc4ac6e394508057a224d92d differ diff --git a/Packages/NB_FX/.git.backup/objects/94/2806dcbf46cbe20b09a0f29e6ccfd147642d68 b/Packages/NB_FX/.git.backup/objects/94/2806dcbf46cbe20b09a0f29e6ccfd147642d68 new file mode 100644 index 00000000..a2626487 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/94/2806dcbf46cbe20b09a0f29e6ccfd147642d68 differ diff --git a/Packages/NB_FX/.git.backup/objects/94/375fddde347eb92e947eb24657833ecf852a13 b/Packages/NB_FX/.git.backup/objects/94/375fddde347eb92e947eb24657833ecf852a13 new file mode 100644 index 00000000..ea78875d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/94/375fddde347eb92e947eb24657833ecf852a13 differ diff --git a/Packages/NB_FX/.git.backup/objects/94/ef59c61a98dbc42a477b6f422ccc63c38f1f04 b/Packages/NB_FX/.git.backup/objects/94/ef59c61a98dbc42a477b6f422ccc63c38f1f04 new file mode 100644 index 00000000..e7759e42 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/94/ef59c61a98dbc42a477b6f422ccc63c38f1f04 differ diff --git a/Packages/NB_FX/.git.backup/objects/95/31274480bd4586f09899583668994960df9fce b/Packages/NB_FX/.git.backup/objects/95/31274480bd4586f09899583668994960df9fce new file mode 100644 index 00000000..57e7a925 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/95/31274480bd4586f09899583668994960df9fce differ diff --git a/Packages/NB_FX/.git.backup/objects/95/526398f9aabebaacdf97b3739f61dd078b3150 b/Packages/NB_FX/.git.backup/objects/95/526398f9aabebaacdf97b3739f61dd078b3150 new file mode 100644 index 00000000..f7452a16 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/95/526398f9aabebaacdf97b3739f61dd078b3150 @@ -0,0 +1,3 @@ +xM +0] "^%/E[)xp/x +b>au"5U9)2 qT8`s$NqHZSlr)9l``h<8vu6RX& N \+RJTZ(s?k-E \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/95/5ae4570a671b16bedeb50e8fae23fbdbdc2a3a b/Packages/NB_FX/.git.backup/objects/95/5ae4570a671b16bedeb50e8fae23fbdbdc2a3a new file mode 100644 index 00000000..e309383d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/95/5ae4570a671b16bedeb50e8fae23fbdbdc2a3a differ diff --git a/Packages/NB_FX/.git.backup/objects/95/a5d543121c5a8ec448f221850a06c066047c06 b/Packages/NB_FX/.git.backup/objects/95/a5d543121c5a8ec448f221850a06c066047c06 new file mode 100644 index 00000000..95246967 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/95/a5d543121c5a8ec448f221850a06c066047c06 differ diff --git a/Packages/NB_FX/.git.backup/objects/95/d0e158b2d8c59c128679e962f4d0d9c9f7e570 b/Packages/NB_FX/.git.backup/objects/95/d0e158b2d8c59c128679e962f4d0d9c9f7e570 new file mode 100644 index 00000000..26ba5f9d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/95/d0e158b2d8c59c128679e962f4d0d9c9f7e570 differ diff --git a/Packages/NB_FX/.git.backup/objects/96/f6c763312c0a1758842fa187e6ba039896dea2 b/Packages/NB_FX/.git.backup/objects/96/f6c763312c0a1758842fa187e6ba039896dea2 new file mode 100644 index 00000000..1a636395 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/96/f6c763312c0a1758842fa187e6ba039896dea2 differ diff --git a/Packages/NB_FX/.git.backup/objects/97/185514fb88fa3ba4a69d0f4dfa4177b77fd3b3 b/Packages/NB_FX/.git.backup/objects/97/185514fb88fa3ba4a69d0f4dfa4177b77fd3b3 new file mode 100644 index 00000000..c38a5a6b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/97/185514fb88fa3ba4a69d0f4dfa4177b77fd3b3 differ diff --git a/Packages/NB_FX/.git.backup/objects/97/8d58a5b540db099451beb0a4327178174cd889 b/Packages/NB_FX/.git.backup/objects/97/8d58a5b540db099451beb0a4327178174cd889 new file mode 100644 index 00000000..a6efe689 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/97/8d58a5b540db099451beb0a4327178174cd889 differ diff --git a/Packages/NB_FX/.git.backup/objects/97/bd98e519b7a36e576eebf6f8a7f0371e2908c0 b/Packages/NB_FX/.git.backup/objects/97/bd98e519b7a36e576eebf6f8a7f0371e2908c0 new file mode 100644 index 00000000..ded4fc85 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/97/bd98e519b7a36e576eebf6f8a7f0371e2908c0 differ diff --git a/Packages/NB_FX/.git.backup/objects/98/b1ebede26342a8c897f649277e06b71d4ce058 b/Packages/NB_FX/.git.backup/objects/98/b1ebede26342a8c897f649277e06b71d4ce058 new file mode 100644 index 00000000..9988d66f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/98/b1ebede26342a8c897f649277e06b71d4ce058 differ diff --git a/Packages/NB_FX/.git.backup/objects/98/fc3711b1bc8ec6c98f9c2b44ecc14008b2d5b4 b/Packages/NB_FX/.git.backup/objects/98/fc3711b1bc8ec6c98f9c2b44ecc14008b2d5b4 new file mode 100644 index 00000000..78f07274 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/98/fc3711b1bc8ec6c98f9c2b44ecc14008b2d5b4 differ diff --git a/Packages/NB_FX/.git.backup/objects/99/2e35750177b6abfc644459281e263b78ae7769 b/Packages/NB_FX/.git.backup/objects/99/2e35750177b6abfc644459281e263b78ae7769 new file mode 100644 index 00000000..29807f0a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/99/2e35750177b6abfc644459281e263b78ae7769 differ diff --git a/Packages/NB_FX/.git.backup/objects/99/851d7aec9468a8e1482093cf97d13c3300ca61 b/Packages/NB_FX/.git.backup/objects/99/851d7aec9468a8e1482093cf97d13c3300ca61 new file mode 100644 index 00000000..65b9e6c8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/99/851d7aec9468a8e1482093cf97d13c3300ca61 differ diff --git a/Packages/NB_FX/.git.backup/objects/99/9d364941d2b29adcb5be8d030bc6f257188ba9 b/Packages/NB_FX/.git.backup/objects/99/9d364941d2b29adcb5be8d030bc6f257188ba9 new file mode 100644 index 00000000..f0535ad4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/99/9d364941d2b29adcb5be8d030bc6f257188ba9 differ diff --git a/Packages/NB_FX/.git.backup/objects/99/f265b6525c12c2cf810e5cb0ddd2b861d49385 b/Packages/NB_FX/.git.backup/objects/99/f265b6525c12c2cf810e5cb0ddd2b861d49385 new file mode 100644 index 00000000..7397c40a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/99/f265b6525c12c2cf810e5cb0ddd2b861d49385 differ diff --git a/Packages/NB_FX/.git.backup/objects/9a/13c5049f795910063721888c18976ee5d90f01 b/Packages/NB_FX/.git.backup/objects/9a/13c5049f795910063721888c18976ee5d90f01 new file mode 100644 index 00000000..ade59cdc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9a/13c5049f795910063721888c18976ee5d90f01 differ diff --git a/Packages/NB_FX/.git.backup/objects/9b/024e3d06c9ea02bd6ef00f8f2ad953b03bec0c b/Packages/NB_FX/.git.backup/objects/9b/024e3d06c9ea02bd6ef00f8f2ad953b03bec0c new file mode 100644 index 00000000..1052786c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9b/024e3d06c9ea02bd6ef00f8f2ad953b03bec0c differ diff --git a/Packages/NB_FX/.git.backup/objects/9b/1aafb18271e05941b0af9d2dc6585c529c4394 b/Packages/NB_FX/.git.backup/objects/9b/1aafb18271e05941b0af9d2dc6585c529c4394 new file mode 100644 index 00000000..1030bdb9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9b/1aafb18271e05941b0af9d2dc6585c529c4394 differ diff --git a/Packages/NB_FX/.git.backup/objects/9b/5d7a64c9a77f693b043e3770ab52e07c9fc1d1 b/Packages/NB_FX/.git.backup/objects/9b/5d7a64c9a77f693b043e3770ab52e07c9fc1d1 new file mode 100644 index 00000000..bd9995d6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9b/5d7a64c9a77f693b043e3770ab52e07c9fc1d1 differ diff --git a/Packages/NB_FX/.git.backup/objects/9c/03d4646a76228903cbe9ac8070d59e5380dfec b/Packages/NB_FX/.git.backup/objects/9c/03d4646a76228903cbe9ac8070d59e5380dfec new file mode 100644 index 00000000..0fa9fea2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9c/03d4646a76228903cbe9ac8070d59e5380dfec differ diff --git a/Packages/NB_FX/.git.backup/objects/9c/3621f1a59e4167bcccfd3359e34b8cd989ad7b b/Packages/NB_FX/.git.backup/objects/9c/3621f1a59e4167bcccfd3359e34b8cd989ad7b new file mode 100644 index 00000000..3bb1f6d1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9c/3621f1a59e4167bcccfd3359e34b8cd989ad7b differ diff --git a/Packages/NB_FX/.git.backup/objects/9c/49edc051d3b93707698ac35d191613c27d8e4e b/Packages/NB_FX/.git.backup/objects/9c/49edc051d3b93707698ac35d191613c27d8e4e new file mode 100644 index 00000000..0c99cf12 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9c/49edc051d3b93707698ac35d191613c27d8e4e differ diff --git a/Packages/NB_FX/.git.backup/objects/9c/8a95100708395eeca295cde92ffc414bdc0d61 b/Packages/NB_FX/.git.backup/objects/9c/8a95100708395eeca295cde92ffc414bdc0d61 new file mode 100644 index 00000000..e419cc4e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9c/8a95100708395eeca295cde92ffc414bdc0d61 differ diff --git a/Packages/NB_FX/.git.backup/objects/9d/5bc8a04ba3458e03f67464295c6e7c7ed8b32f b/Packages/NB_FX/.git.backup/objects/9d/5bc8a04ba3458e03f67464295c6e7c7ed8b32f new file mode 100644 index 00000000..8052f9e3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9d/5bc8a04ba3458e03f67464295c6e7c7ed8b32f differ diff --git a/Packages/NB_FX/.git.backup/objects/9e/1fa944ae8116f8c9633e84cda51f9b3d8c2f99 b/Packages/NB_FX/.git.backup/objects/9e/1fa944ae8116f8c9633e84cda51f9b3d8c2f99 new file mode 100644 index 00000000..83bf78a0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9e/1fa944ae8116f8c9633e84cda51f9b3d8c2f99 differ diff --git a/Packages/NB_FX/.git.backup/objects/9e/4de36b587a2d376b9a0291745d8bc19ec345e5 b/Packages/NB_FX/.git.backup/objects/9e/4de36b587a2d376b9a0291745d8bc19ec345e5 new file mode 100644 index 00000000..015b8642 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9e/4de36b587a2d376b9a0291745d8bc19ec345e5 differ diff --git a/Packages/NB_FX/.git.backup/objects/9e/bbdd03de018a9b06aca2df3e29e55c87560958 b/Packages/NB_FX/.git.backup/objects/9e/bbdd03de018a9b06aca2df3e29e55c87560958 new file mode 100644 index 00000000..1fb32aa0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9e/bbdd03de018a9b06aca2df3e29e55c87560958 differ diff --git a/Packages/NB_FX/.git.backup/objects/9f/095e48c5d4dfe2bedc9353e14307b56271dfe4 b/Packages/NB_FX/.git.backup/objects/9f/095e48c5d4dfe2bedc9353e14307b56271dfe4 new file mode 100644 index 00000000..7ac351b3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9f/095e48c5d4dfe2bedc9353e14307b56271dfe4 differ diff --git a/Packages/NB_FX/.git.backup/objects/9f/12f0d7e21c48fe0d35e1d1bfe6c3235d8ced8b b/Packages/NB_FX/.git.backup/objects/9f/12f0d7e21c48fe0d35e1d1bfe6c3235d8ced8b new file mode 100644 index 00000000..ea12e018 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9f/12f0d7e21c48fe0d35e1d1bfe6c3235d8ced8b differ diff --git a/Packages/NB_FX/.git.backup/objects/9f/60e8508d4d514d6efc7223cb6f44aa4cf0402e b/Packages/NB_FX/.git.backup/objects/9f/60e8508d4d514d6efc7223cb6f44aa4cf0402e new file mode 100644 index 00000000..6027da87 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9f/60e8508d4d514d6efc7223cb6f44aa4cf0402e differ diff --git a/Packages/NB_FX/.git.backup/objects/9f/8c1bc8e6aaf2e04a5daa3fc9f77ab3f876c429 b/Packages/NB_FX/.git.backup/objects/9f/8c1bc8e6aaf2e04a5daa3fc9f77ab3f876c429 new file mode 100644 index 00000000..f2ca52af Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/9f/8c1bc8e6aaf2e04a5daa3fc9f77ab3f876c429 differ diff --git a/Packages/NB_FX/.git.backup/objects/a0/31a38de067376c1fa49902963938eb06a3acde b/Packages/NB_FX/.git.backup/objects/a0/31a38de067376c1fa49902963938eb06a3acde new file mode 100644 index 00000000..96955b6b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a0/31a38de067376c1fa49902963938eb06a3acde differ diff --git a/Packages/NB_FX/.git.backup/objects/a0/5bea7d9af691f697504d728eb06fb34df99aa9 b/Packages/NB_FX/.git.backup/objects/a0/5bea7d9af691f697504d728eb06fb34df99aa9 new file mode 100644 index 00000000..086d3263 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a0/5bea7d9af691f697504d728eb06fb34df99aa9 differ diff --git a/Packages/NB_FX/.git.backup/objects/a1/2b86e2d8bb60adc81435ffa3fb5c55450af59c b/Packages/NB_FX/.git.backup/objects/a1/2b86e2d8bb60adc81435ffa3fb5c55450af59c new file mode 100644 index 00000000..a9e87267 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a1/2b86e2d8bb60adc81435ffa3fb5c55450af59c differ diff --git a/Packages/NB_FX/.git.backup/objects/a1/6d31d996e905cb8bf3ff8ca5cb9e8a45bbf147 b/Packages/NB_FX/.git.backup/objects/a1/6d31d996e905cb8bf3ff8ca5cb9e8a45bbf147 new file mode 100644 index 00000000..0e626e64 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/a1/6d31d996e905cb8bf3ff8ca5cb9e8a45bbf147 @@ -0,0 +1,4 @@ +x+)JMU054g040031QK,I,))L*-I-fH[׮;{m9;QH*3R'>=Rfӓij^U_\PZ\Zqe{tD;5W P@Wx]NV35vɃHLI-*gÒ$?O]}?PB$I= ɎYtӌ %j#º7{_Ί֍fO&<zhm|+E&pPjЍ%9%cn+_zUW^~urX51h*U:pг +GP[ +S +עd8k˅ǢR"ϥ->Fxv`>۞ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/a1/877d301c883a262befc3fc5148765efaf58950 b/Packages/NB_FX/.git.backup/objects/a1/877d301c883a262befc3fc5148765efaf58950 new file mode 100644 index 00000000..4fc82678 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a1/877d301c883a262befc3fc5148765efaf58950 differ diff --git a/Packages/NB_FX/.git.backup/objects/a1/b10816d3a7677e7c8019f55cbc7264ab57609f b/Packages/NB_FX/.git.backup/objects/a1/b10816d3a7677e7c8019f55cbc7264ab57609f new file mode 100644 index 00000000..2302c464 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a1/b10816d3a7677e7c8019f55cbc7264ab57609f differ diff --git a/Packages/NB_FX/.git.backup/objects/a2/97ef056527552dc1bff1b5a9577dab062bd899 b/Packages/NB_FX/.git.backup/objects/a2/97ef056527552dc1bff1b5a9577dab062bd899 new file mode 100644 index 00000000..c0cca493 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a2/97ef056527552dc1bff1b5a9577dab062bd899 differ diff --git a/Packages/NB_FX/.git.backup/objects/a3/10bdfb946252ce579e25e7605b47e27b5fe5fe b/Packages/NB_FX/.git.backup/objects/a3/10bdfb946252ce579e25e7605b47e27b5fe5fe new file mode 100644 index 00000000..dcd28434 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a3/10bdfb946252ce579e25e7605b47e27b5fe5fe differ diff --git a/Packages/NB_FX/.git.backup/objects/a3/70c4c4f3628f2fc74fe3f61fbc06b76cfe0675 b/Packages/NB_FX/.git.backup/objects/a3/70c4c4f3628f2fc74fe3f61fbc06b76cfe0675 new file mode 100644 index 00000000..e2fe913d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a3/70c4c4f3628f2fc74fe3f61fbc06b76cfe0675 differ diff --git a/Packages/NB_FX/.git.backup/objects/a3/fa739d79c2759588a99d33f292cefee3b52dae b/Packages/NB_FX/.git.backup/objects/a3/fa739d79c2759588a99d33f292cefee3b52dae new file mode 100644 index 00000000..2b621221 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/a3/fa739d79c2759588a99d33f292cefee3b52dae @@ -0,0 +1,2 @@ +xK +0 )/?PJ"2"I8W( -˫|*XiZIk*rv)"ZL.|! 9rf޲!&Gq(hH[GxRn]"F>o;|OY[&D3mqC\1!aǽ&7Y82zA. \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/a4/0d54d5e84c976d51e27ed0aade400ec00a2fae b/Packages/NB_FX/.git.backup/objects/a4/0d54d5e84c976d51e27ed0aade400ec00a2fae new file mode 100644 index 00000000..59c8ee45 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a4/0d54d5e84c976d51e27ed0aade400ec00a2fae differ diff --git a/Packages/NB_FX/.git.backup/objects/a4/1fcb317eeb41adda4e4616f0a429d444e30692 b/Packages/NB_FX/.git.backup/objects/a4/1fcb317eeb41adda4e4616f0a429d444e30692 new file mode 100644 index 00000000..ea9c3de0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a4/1fcb317eeb41adda4e4616f0a429d444e30692 differ diff --git a/Packages/NB_FX/.git.backup/objects/a4/3315012eda1c5d697b3dd098938a208bfcc340 b/Packages/NB_FX/.git.backup/objects/a4/3315012eda1c5d697b3dd098938a208bfcc340 new file mode 100644 index 00000000..00a652b9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a4/3315012eda1c5d697b3dd098938a208bfcc340 differ diff --git a/Packages/NB_FX/.git.backup/objects/a5/174b5211103998f9424de54e184166d472a541 b/Packages/NB_FX/.git.backup/objects/a5/174b5211103998f9424de54e184166d472a541 new file mode 100644 index 00000000..41c0ddf0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a5/174b5211103998f9424de54e184166d472a541 differ diff --git a/Packages/NB_FX/.git.backup/objects/a5/309fc48405c2f6d089101b3b693d4447b612bb b/Packages/NB_FX/.git.backup/objects/a5/309fc48405c2f6d089101b3b693d4447b612bb new file mode 100644 index 00000000..1d500835 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a5/309fc48405c2f6d089101b3b693d4447b612bb differ diff --git a/Packages/NB_FX/.git.backup/objects/a5/9fadbdd15d739e9e9491e5ba783164b33168c8 b/Packages/NB_FX/.git.backup/objects/a5/9fadbdd15d739e9e9491e5ba783164b33168c8 new file mode 100644 index 00000000..4d361322 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a5/9fadbdd15d739e9e9491e5ba783164b33168c8 differ diff --git a/Packages/NB_FX/.git.backup/objects/a5/b66050a27ca91d829363b54fedc545f5c4d109 b/Packages/NB_FX/.git.backup/objects/a5/b66050a27ca91d829363b54fedc545f5c4d109 new file mode 100644 index 00000000..c92bf0a1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a5/b66050a27ca91d829363b54fedc545f5c4d109 differ diff --git a/Packages/NB_FX/.git.backup/objects/a6/171ec13d650fd3bd8d8625ef58d559b56a6c5b b/Packages/NB_FX/.git.backup/objects/a6/171ec13d650fd3bd8d8625ef58d559b56a6c5b new file mode 100644 index 00000000..1462acdb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a6/171ec13d650fd3bd8d8625ef58d559b56a6c5b differ diff --git a/Packages/NB_FX/.git.backup/objects/a6/252a3e924eeb8ed1a42298c0dd31c971df67b9 b/Packages/NB_FX/.git.backup/objects/a6/252a3e924eeb8ed1a42298c0dd31c971df67b9 new file mode 100644 index 00000000..ee03e2f1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a6/252a3e924eeb8ed1a42298c0dd31c971df67b9 differ diff --git a/Packages/NB_FX/.git.backup/objects/a6/27e7c0ec61f01a36b3026323469e2bff7b67b9 b/Packages/NB_FX/.git.backup/objects/a6/27e7c0ec61f01a36b3026323469e2bff7b67b9 new file mode 100644 index 00000000..826cb78d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a6/27e7c0ec61f01a36b3026323469e2bff7b67b9 differ diff --git a/Packages/NB_FX/.git.backup/objects/a6/44f337563a1a7b1c8ce4d05fb81b3f7f085ab6 b/Packages/NB_FX/.git.backup/objects/a6/44f337563a1a7b1c8ce4d05fb81b3f7f085ab6 new file mode 100644 index 00000000..63a2550b --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/a6/44f337563a1a7b1c8ce4d05fb81b3f7f085ab6 @@ -0,0 +1,3 @@ +x+)JMU054g040031QK,I,))L*-I-fH[׮;{m9;QH*3R'>=Rfӓij^U_\PZ\Zqe{tD;5W P@W>ɦvK"|-ㄛZT 1tφ%?NI.]sTp~P .Ske:bC}K_,n8#Ww_XfOY1_غь3b.*es}9oj^DibZYR 1:.l]uzY,UCeS+')XUmfP[ +S +עd8k˅ǢR"ϥ->Fxv`fd \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/a6/6289f2c37d2b29653d289a2fd59631deaafc2b b/Packages/NB_FX/.git.backup/objects/a6/6289f2c37d2b29653d289a2fd59631deaafc2b new file mode 100644 index 00000000..6c64be0f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a6/6289f2c37d2b29653d289a2fd59631deaafc2b differ diff --git a/Packages/NB_FX/.git.backup/objects/a6/b0ca7a63adc9e9a51fb2ed2e60e5b98e07417d b/Packages/NB_FX/.git.backup/objects/a6/b0ca7a63adc9e9a51fb2ed2e60e5b98e07417d new file mode 100644 index 00000000..4253c9f8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a6/b0ca7a63adc9e9a51fb2ed2e60e5b98e07417d differ diff --git a/Packages/NB_FX/.git.backup/objects/a6/ffdab187ebe80db213e0e1bfa32445e9f80a0d b/Packages/NB_FX/.git.backup/objects/a6/ffdab187ebe80db213e0e1bfa32445e9f80a0d new file mode 100644 index 00000000..9577cbf7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a6/ffdab187ebe80db213e0e1bfa32445e9f80a0d differ diff --git a/Packages/NB_FX/.git.backup/objects/a7/95c9a9714fdc344337d150c731f56ec3987529 b/Packages/NB_FX/.git.backup/objects/a7/95c9a9714fdc344337d150c731f56ec3987529 new file mode 100644 index 00000000..af6790b3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a7/95c9a9714fdc344337d150c731f56ec3987529 differ diff --git a/Packages/NB_FX/.git.backup/objects/a7/c4dc66d750663b59c6a20a45f5e74f28af6021 b/Packages/NB_FX/.git.backup/objects/a7/c4dc66d750663b59c6a20a45f5e74f28af6021 new file mode 100644 index 00000000..981bce50 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a7/c4dc66d750663b59c6a20a45f5e74f28af6021 differ diff --git a/Packages/NB_FX/.git.backup/objects/a7/c803838a5c07748a5bbb5f2856817f07e4ef84 b/Packages/NB_FX/.git.backup/objects/a7/c803838a5c07748a5bbb5f2856817f07e4ef84 new file mode 100644 index 00000000..d84caf0a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a7/c803838a5c07748a5bbb5f2856817f07e4ef84 differ diff --git a/Packages/NB_FX/.git.backup/objects/a7/e72cd2c66a1ba992eec99b76f4f7a8c4660279 b/Packages/NB_FX/.git.backup/objects/a7/e72cd2c66a1ba992eec99b76f4f7a8c4660279 new file mode 100644 index 00000000..bcf5f85e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a7/e72cd2c66a1ba992eec99b76f4f7a8c4660279 differ diff --git a/Packages/NB_FX/.git.backup/objects/a7/fa280604f1a83e024a836137f00eb13ddeb27b b/Packages/NB_FX/.git.backup/objects/a7/fa280604f1a83e024a836137f00eb13ddeb27b new file mode 100644 index 00000000..fe417b1e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a7/fa280604f1a83e024a836137f00eb13ddeb27b differ diff --git a/Packages/NB_FX/.git.backup/objects/a8/2216d4b9d20a5399acad779e46c6cab185c953 b/Packages/NB_FX/.git.backup/objects/a8/2216d4b9d20a5399acad779e46c6cab185c953 new file mode 100644 index 00000000..5576fed4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/a8/2216d4b9d20a5399acad779e46c6cab185c953 differ diff --git a/Packages/NB_FX/.git.backup/objects/a8/617a233fb38e322ab3ae9bd5bf36b6ab0cbe87 b/Packages/NB_FX/.git.backup/objects/a8/617a233fb38e322ab3ae9bd5bf36b6ab0cbe87 new file mode 100644 index 00000000..4ab20f8b --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/a8/617a233fb38e322ab3ae9bd5bf36b6ab0cbe87 @@ -0,0 +1,2 @@ +xRn0 9_/@IT\em-iKR'm„eg\6}}iĔߐvhp[-dJܓX\2k*;Y'Y?A6'̙T79IC(umeuJndA2o((;T%J߼< 7;8#1%b K\>w0C +햑]zBpP"J@8(5В̜̒J1HLpat+/?Xͺ`9hf]x#{cS?P[ +S +עd8k˅ǢR"ϥ->Fxv`p@ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/ac/be36b557bf870815a6875de919d0be145771a0 b/Packages/NB_FX/.git.backup/objects/ac/be36b557bf870815a6875de919d0be145771a0 new file mode 100644 index 00000000..ff59a126 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ac/be36b557bf870815a6875de919d0be145771a0 differ diff --git a/Packages/NB_FX/.git.backup/objects/ad/9f698968d2b89b5d82dd031ce7ce5c2c7cde80 b/Packages/NB_FX/.git.backup/objects/ad/9f698968d2b89b5d82dd031ce7ce5c2c7cde80 new file mode 100644 index 00000000..61f8e0a5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ad/9f698968d2b89b5d82dd031ce7ce5c2c7cde80 differ diff --git a/Packages/NB_FX/.git.backup/objects/ad/ac43e191690db355c6e82496db6f3d1550761d b/Packages/NB_FX/.git.backup/objects/ad/ac43e191690db355c6e82496db6f3d1550761d new file mode 100644 index 00000000..597ae200 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ad/ac43e191690db355c6e82496db6f3d1550761d differ diff --git a/Packages/NB_FX/.git.backup/objects/ad/e534bb0b26316c12fd885fa79daa1f477c62a1 b/Packages/NB_FX/.git.backup/objects/ad/e534bb0b26316c12fd885fa79daa1f477c62a1 new file mode 100644 index 00000000..7ac180a7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ad/e534bb0b26316c12fd885fa79daa1f477c62a1 differ diff --git a/Packages/NB_FX/.git.backup/objects/ae/86975cca30fadff3e4d790f7be8bd2fc0c4a63 b/Packages/NB_FX/.git.backup/objects/ae/86975cca30fadff3e4d790f7be8bd2fc0c4a63 new file mode 100644 index 00000000..0c9e202c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ae/86975cca30fadff3e4d790f7be8bd2fc0c4a63 differ diff --git a/Packages/NB_FX/.git.backup/objects/ae/a00e1926ffe6feaacc140aee9076de485512a1 b/Packages/NB_FX/.git.backup/objects/ae/a00e1926ffe6feaacc140aee9076de485512a1 new file mode 100644 index 00000000..8ae535a1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ae/a00e1926ffe6feaacc140aee9076de485512a1 differ diff --git a/Packages/NB_FX/.git.backup/objects/ae/d57f8dbd51263e150496b61a0713349724866d b/Packages/NB_FX/.git.backup/objects/ae/d57f8dbd51263e150496b61a0713349724866d new file mode 100644 index 00000000..3441f26b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ae/d57f8dbd51263e150496b61a0713349724866d differ diff --git a/Packages/NB_FX/.git.backup/objects/ae/e19395be4876440c0bfb1b96d9834e0f0751fb b/Packages/NB_FX/.git.backup/objects/ae/e19395be4876440c0bfb1b96d9834e0f0751fb new file mode 100644 index 00000000..fe06fe64 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ae/e19395be4876440c0bfb1b96d9834e0f0751fb differ diff --git a/Packages/NB_FX/.git.backup/objects/af/26268a037981f0e7c85412d72e5f3df3689609 b/Packages/NB_FX/.git.backup/objects/af/26268a037981f0e7c85412d72e5f3df3689609 new file mode 100644 index 00000000..c525707a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/af/26268a037981f0e7c85412d72e5f3df3689609 differ diff --git a/Packages/NB_FX/.git.backup/objects/af/4df172fddc60724c254552e6098276f4d4b199 b/Packages/NB_FX/.git.backup/objects/af/4df172fddc60724c254552e6098276f4d4b199 new file mode 100644 index 00000000..8cef9d83 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/af/4df172fddc60724c254552e6098276f4d4b199 differ diff --git a/Packages/NB_FX/.git.backup/objects/af/6aca214ef667e1dac7b08f987ca6d9d4d763c3 b/Packages/NB_FX/.git.backup/objects/af/6aca214ef667e1dac7b08f987ca6d9d4d763c3 new file mode 100644 index 00000000..6d0ababf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/af/6aca214ef667e1dac7b08f987ca6d9d4d763c3 differ diff --git a/Packages/NB_FX/.git.backup/objects/b0/5e01fa88e9860e504439b7683adff167a12340 b/Packages/NB_FX/.git.backup/objects/b0/5e01fa88e9860e504439b7683adff167a12340 new file mode 100644 index 00000000..75edb05d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b0/5e01fa88e9860e504439b7683adff167a12340 differ diff --git a/Packages/NB_FX/.git.backup/objects/b0/c261d9a28b075af002528788126cfa318a4da8 b/Packages/NB_FX/.git.backup/objects/b0/c261d9a28b075af002528788126cfa318a4da8 new file mode 100644 index 00000000..fdfc8765 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b0/c261d9a28b075af002528788126cfa318a4da8 differ diff --git a/Packages/NB_FX/.git.backup/objects/b1/bff935103903157c8c46d0e457936bd80c69e9 b/Packages/NB_FX/.git.backup/objects/b1/bff935103903157c8c46d0e457936bd80c69e9 new file mode 100644 index 00000000..c6034b29 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b1/bff935103903157c8c46d0e457936bd80c69e9 differ diff --git a/Packages/NB_FX/.git.backup/objects/b2/3e2db0084240d82ac79e44cf510bd96579aca8 b/Packages/NB_FX/.git.backup/objects/b2/3e2db0084240d82ac79e44cf510bd96579aca8 new file mode 100644 index 00000000..efc7c893 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b2/3e2db0084240d82ac79e44cf510bd96579aca8 differ diff --git a/Packages/NB_FX/.git.backup/objects/b3/0cb19cd2f2cc1f02939698f7608c53078acd7c b/Packages/NB_FX/.git.backup/objects/b3/0cb19cd2f2cc1f02939698f7608c53078acd7c new file mode 100644 index 00000000..70b3aeb6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b3/0cb19cd2f2cc1f02939698f7608c53078acd7c differ diff --git a/Packages/NB_FX/.git.backup/objects/b3/6d855dd9da932ff837e00a3aac8575f34fa77c b/Packages/NB_FX/.git.backup/objects/b3/6d855dd9da932ff837e00a3aac8575f34fa77c new file mode 100644 index 00000000..e619f352 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b3/6d855dd9da932ff837e00a3aac8575f34fa77c differ diff --git a/Packages/NB_FX/.git.backup/objects/b3/cc871040d8ee94d5cc2f030ca14e8b4f0d2bd3 b/Packages/NB_FX/.git.backup/objects/b3/cc871040d8ee94d5cc2f030ca14e8b4f0d2bd3 new file mode 100644 index 00000000..500f301f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b3/cc871040d8ee94d5cc2f030ca14e8b4f0d2bd3 differ diff --git a/Packages/NB_FX/.git.backup/objects/b3/daa76e89ce95dfcfa3bf6a49f842c6207ca157 b/Packages/NB_FX/.git.backup/objects/b3/daa76e89ce95dfcfa3bf6a49f842c6207ca157 new file mode 100644 index 00000000..a0a1a74e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b3/daa76e89ce95dfcfa3bf6a49f842c6207ca157 differ diff --git a/Packages/NB_FX/.git.backup/objects/b4/b63fcefeb88060701d0e70b654eb669e8800bc b/Packages/NB_FX/.git.backup/objects/b4/b63fcefeb88060701d0e70b654eb669e8800bc new file mode 100644 index 00000000..756ee08f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b4/b63fcefeb88060701d0e70b654eb669e8800bc differ diff --git a/Packages/NB_FX/.git.backup/objects/b4/b8d3a768e7c099752dae109a2c7bb580eb9202 b/Packages/NB_FX/.git.backup/objects/b4/b8d3a768e7c099752dae109a2c7bb580eb9202 new file mode 100644 index 00000000..1ec333a1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b4/b8d3a768e7c099752dae109a2c7bb580eb9202 differ diff --git a/Packages/NB_FX/.git.backup/objects/b5/4a016e47045935f56b67e55dd1de684a4ea879 b/Packages/NB_FX/.git.backup/objects/b5/4a016e47045935f56b67e55dd1de684a4ea879 new file mode 100644 index 00000000..864e4edc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b5/4a016e47045935f56b67e55dd1de684a4ea879 differ diff --git a/Packages/NB_FX/.git.backup/objects/b5/81ae96067394504460b56f70a7498709d04ca1 b/Packages/NB_FX/.git.backup/objects/b5/81ae96067394504460b56f70a7498709d04ca1 new file mode 100644 index 00000000..a701d386 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b5/81ae96067394504460b56f70a7498709d04ca1 differ diff --git a/Packages/NB_FX/.git.backup/objects/b5/9332321982602c5ce4d0af816c9abbda0d7d7b b/Packages/NB_FX/.git.backup/objects/b5/9332321982602c5ce4d0af816c9abbda0d7d7b new file mode 100644 index 00000000..35aeeb5b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b5/9332321982602c5ce4d0af816c9abbda0d7d7b differ diff --git a/Packages/NB_FX/.git.backup/objects/b5/9dd06e7a2a282cc733b95eeb9eafc41d7d45b8 b/Packages/NB_FX/.git.backup/objects/b5/9dd06e7a2a282cc733b95eeb9eafc41d7d45b8 new file mode 100644 index 00000000..3c103c71 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b5/9dd06e7a2a282cc733b95eeb9eafc41d7d45b8 differ diff --git a/Packages/NB_FX/.git.backup/objects/b5/a8a5dfbce513d0ff57b1e1bc3f9d8ad7dd02cb b/Packages/NB_FX/.git.backup/objects/b5/a8a5dfbce513d0ff57b1e1bc3f9d8ad7dd02cb new file mode 100644 index 00000000..4e55d3ba Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b5/a8a5dfbce513d0ff57b1e1bc3f9d8ad7dd02cb differ diff --git a/Packages/NB_FX/.git.backup/objects/b5/e9763e7e71b0a2b14d07a8416ef586f0184bdd b/Packages/NB_FX/.git.backup/objects/b5/e9763e7e71b0a2b14d07a8416ef586f0184bdd new file mode 100644 index 00000000..bf2d8dcc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b5/e9763e7e71b0a2b14d07a8416ef586f0184bdd differ diff --git a/Packages/NB_FX/.git.backup/objects/b6/531f548f537df756f164544b0d3fda96f533bd b/Packages/NB_FX/.git.backup/objects/b6/531f548f537df756f164544b0d3fda96f533bd new file mode 100644 index 00000000..607c2b49 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b6/531f548f537df756f164544b0d3fda96f533bd differ diff --git a/Packages/NB_FX/.git.backup/objects/b6/e1b7b5a6dfbc8b8971517cae0f790a14fda9af b/Packages/NB_FX/.git.backup/objects/b6/e1b7b5a6dfbc8b8971517cae0f790a14fda9af new file mode 100644 index 00000000..8e951d33 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/b6/e1b7b5a6dfbc8b8971517cae0f790a14fda9af @@ -0,0 +1,4 @@ +x= +1s%W&/hf^,;=Xx%Ž0|ں^e.厈c +0*%MZiQ'wd^R!htW@ qZJ]yv|fKl +BR\l6s c`{\^}: pZRJ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/b7/dba15a2acb9aa1ad666ccc716ab039564df2b7 b/Packages/NB_FX/.git.backup/objects/b7/dba15a2acb9aa1ad666ccc716ab039564df2b7 new file mode 100644 index 00000000..cbb831e3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b7/dba15a2acb9aa1ad666ccc716ab039564df2b7 differ diff --git a/Packages/NB_FX/.git.backup/objects/b8/29e78f259cb55930e37ded995e109792367b28 b/Packages/NB_FX/.git.backup/objects/b8/29e78f259cb55930e37ded995e109792367b28 new file mode 100644 index 00000000..2dce9b32 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/b8/29e78f259cb55930e37ded995e109792367b28 @@ -0,0 +1,6 @@ +x+)JMU016g040031Qs +/. (ON-.KM-Idpʸ~=:"KV횫`gY5L0 +3> ֆZT 1tφ%?NI.]sTp~P ]%.p`􉎡7M3gdy I|9+& [7qF { +P"J@8(5В̜̒J1HLpat+/?Xͺ`9h^HL+lrIʏRaP[ +S +עd8k˅ǢR"ϥ->Fxv`^ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/b8/81e1b0cfdbf35d5748eb3f8af62e4187277172 b/Packages/NB_FX/.git.backup/objects/b8/81e1b0cfdbf35d5748eb3f8af62e4187277172 new file mode 100644 index 00000000..14c991ff Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b8/81e1b0cfdbf35d5748eb3f8af62e4187277172 differ diff --git a/Packages/NB_FX/.git.backup/objects/b8/ca5e1039156563f6e4a2b5b4f14df9ae34a783 b/Packages/NB_FX/.git.backup/objects/b8/ca5e1039156563f6e4a2b5b4f14df9ae34a783 new file mode 100644 index 00000000..f82e8699 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b8/ca5e1039156563f6e4a2b5b4f14df9ae34a783 differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/15fc62f5cf68da0d4f9aefeaaac456e1462890 b/Packages/NB_FX/.git.backup/objects/b9/15fc62f5cf68da0d4f9aefeaaac456e1462890 new file mode 100644 index 00000000..f044d951 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/15fc62f5cf68da0d4f9aefeaaac456e1462890 differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/3e11f378b92a413ee8116cf30547f741533a9b b/Packages/NB_FX/.git.backup/objects/b9/3e11f378b92a413ee8116cf30547f741533a9b new file mode 100644 index 00000000..c0ba8db9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/3e11f378b92a413ee8116cf30547f741533a9b differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/4c0e64c6b884c453bc210dff70b7e5fa26e182 b/Packages/NB_FX/.git.backup/objects/b9/4c0e64c6b884c453bc210dff70b7e5fa26e182 new file mode 100644 index 00000000..da579d04 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/4c0e64c6b884c453bc210dff70b7e5fa26e182 differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/7e8be1456ef3991a5621780dcc4ca1be51bb2b b/Packages/NB_FX/.git.backup/objects/b9/7e8be1456ef3991a5621780dcc4ca1be51bb2b new file mode 100644 index 00000000..9e360811 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/7e8be1456ef3991a5621780dcc4ca1be51bb2b differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/83033de0c09532d2ee7773088f6767a901987a b/Packages/NB_FX/.git.backup/objects/b9/83033de0c09532d2ee7773088f6767a901987a new file mode 100644 index 00000000..47189c42 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/83033de0c09532d2ee7773088f6767a901987a differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/bd4022bcbe1b981d93168f51cfb713a29b5802 b/Packages/NB_FX/.git.backup/objects/b9/bd4022bcbe1b981d93168f51cfb713a29b5802 new file mode 100644 index 00000000..5b452161 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/bd4022bcbe1b981d93168f51cfb713a29b5802 differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/d4db10da92c13add85d7b7bb1d22ca327b96eb b/Packages/NB_FX/.git.backup/objects/b9/d4db10da92c13add85d7b7bb1d22ca327b96eb new file mode 100644 index 00000000..3021b413 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/d4db10da92c13add85d7b7bb1d22ca327b96eb differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/dd184171bc93ccc300afadb6fab0cf8a077301 b/Packages/NB_FX/.git.backup/objects/b9/dd184171bc93ccc300afadb6fab0cf8a077301 new file mode 100644 index 00000000..85cc414a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/dd184171bc93ccc300afadb6fab0cf8a077301 differ diff --git a/Packages/NB_FX/.git.backup/objects/b9/f43ba61bfb1a4a1616166f6734a1f49764de1f b/Packages/NB_FX/.git.backup/objects/b9/f43ba61bfb1a4a1616166f6734a1f49764de1f new file mode 100644 index 00000000..7a3a4a95 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/b9/f43ba61bfb1a4a1616166f6734a1f49764de1f differ diff --git a/Packages/NB_FX/.git.backup/objects/ba/3fb47320ea11153894472f5f795f17246e6403 b/Packages/NB_FX/.git.backup/objects/ba/3fb47320ea11153894472f5f795f17246e6403 new file mode 100644 index 00000000..269e92d9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ba/3fb47320ea11153894472f5f795f17246e6403 differ diff --git a/Packages/NB_FX/.git.backup/objects/bb/5248a27dd9521602e5ee0ac2265b31bce1a850 b/Packages/NB_FX/.git.backup/objects/bb/5248a27dd9521602e5ee0ac2265b31bce1a850 new file mode 100644 index 00000000..2e8dcf20 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bb/5248a27dd9521602e5ee0ac2265b31bce1a850 differ diff --git a/Packages/NB_FX/.git.backup/objects/bb/864f29877fee90ec66f2b7ae52ac5596e5ea50 b/Packages/NB_FX/.git.backup/objects/bb/864f29877fee90ec66f2b7ae52ac5596e5ea50 new file mode 100644 index 00000000..e12f808d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bb/864f29877fee90ec66f2b7ae52ac5596e5ea50 differ diff --git a/Packages/NB_FX/.git.backup/objects/bb/b12f5322d1dea899280f41c4be0aa0f1c02e40 b/Packages/NB_FX/.git.backup/objects/bb/b12f5322d1dea899280f41c4be0aa0f1c02e40 new file mode 100644 index 00000000..5d5c50c7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bb/b12f5322d1dea899280f41c4be0aa0f1c02e40 differ diff --git a/Packages/NB_FX/.git.backup/objects/bb/d977a2f4e00f190cdc144ba058e66cc1c346df b/Packages/NB_FX/.git.backup/objects/bb/d977a2f4e00f190cdc144ba058e66cc1c346df new file mode 100644 index 00000000..10b463d5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bb/d977a2f4e00f190cdc144ba058e66cc1c346df differ diff --git a/Packages/NB_FX/.git.backup/objects/bc/226d8437f284e344f9ed1008eb5d45cbbe5f4e b/Packages/NB_FX/.git.backup/objects/bc/226d8437f284e344f9ed1008eb5d45cbbe5f4e new file mode 100644 index 00000000..1a6ccd19 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bc/226d8437f284e344f9ed1008eb5d45cbbe5f4e differ diff --git a/Packages/NB_FX/.git.backup/objects/bc/67b15be2f171a36ac116622075a9fc9935f490 b/Packages/NB_FX/.git.backup/objects/bc/67b15be2f171a36ac116622075a9fc9935f490 new file mode 100644 index 00000000..695f1587 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bc/67b15be2f171a36ac116622075a9fc9935f490 differ diff --git a/Packages/NB_FX/.git.backup/objects/bc/7bd40bbe66194514a9c126541240fdbc1d2adf b/Packages/NB_FX/.git.backup/objects/bc/7bd40bbe66194514a9c126541240fdbc1d2adf new file mode 100644 index 00000000..040fc124 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bc/7bd40bbe66194514a9c126541240fdbc1d2adf differ diff --git a/Packages/NB_FX/.git.backup/objects/bc/e8bbe477657a2c3873a85410ac7f0133c6b85b b/Packages/NB_FX/.git.backup/objects/bc/e8bbe477657a2c3873a85410ac7f0133c6b85b new file mode 100644 index 00000000..73f39b54 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/bc/e8bbe477657a2c3873a85410ac7f0133c6b85b @@ -0,0 +1 @@ +x]J@=)Be.x؋xkdd2#$ފZBZh0)o\ŧhiޚK37̳3/f qt=NGvD9\wX}+-ȞY 8n>!#kzE+cQn>r}KA}hQμv?R \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/bd/56c391b5e8f098c505b93db60311ae7a00ee25 b/Packages/NB_FX/.git.backup/objects/bd/56c391b5e8f098c505b93db60311ae7a00ee25 new file mode 100644 index 00000000..f7c517b1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bd/56c391b5e8f098c505b93db60311ae7a00ee25 differ diff --git a/Packages/NB_FX/.git.backup/objects/bd/612416913336f30c7a74c82d2555cd1338d670 b/Packages/NB_FX/.git.backup/objects/bd/612416913336f30c7a74c82d2555cd1338d670 new file mode 100644 index 00000000..44b44f8e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bd/612416913336f30c7a74c82d2555cd1338d670 differ diff --git a/Packages/NB_FX/.git.backup/objects/bd/83306f57a370fdae222be8b33a06304650d536 b/Packages/NB_FX/.git.backup/objects/bd/83306f57a370fdae222be8b33a06304650d536 new file mode 100644 index 00000000..6bf61426 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/bd/83306f57a370fdae222be8b33a06304650d536 differ diff --git a/Packages/NB_FX/.git.backup/objects/be/2e96443521cb8be615b4b9be3bc7cc917bfa8d b/Packages/NB_FX/.git.backup/objects/be/2e96443521cb8be615b4b9be3bc7cc917bfa8d new file mode 100644 index 00000000..d734523a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/be/2e96443521cb8be615b4b9be3bc7cc917bfa8d differ diff --git a/Packages/NB_FX/.git.backup/objects/be/8f5f6970ba2d6ca6ce91b6f074b6301e1d07a1 b/Packages/NB_FX/.git.backup/objects/be/8f5f6970ba2d6ca6ce91b6f074b6301e1d07a1 new file mode 100644 index 00000000..e3a0afdd Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/be/8f5f6970ba2d6ca6ce91b6f074b6301e1d07a1 differ diff --git a/Packages/NB_FX/.git.backup/objects/be/a4f141d643c0a27789160c64f5436736c2bd37 b/Packages/NB_FX/.git.backup/objects/be/a4f141d643c0a27789160c64f5436736c2bd37 new file mode 100644 index 00000000..04f57408 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/be/a4f141d643c0a27789160c64f5436736c2bd37 differ diff --git a/Packages/NB_FX/.git.backup/objects/c0/231ca4dc66d3fd8490580a8ce6c8a431e1caa7 b/Packages/NB_FX/.git.backup/objects/c0/231ca4dc66d3fd8490580a8ce6c8a431e1caa7 new file mode 100644 index 00000000..e8f79b0a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c0/231ca4dc66d3fd8490580a8ce6c8a431e1caa7 differ diff --git a/Packages/NB_FX/.git.backup/objects/c0/52da76fef50a504ef6533359b349f2c8aa4fe6 b/Packages/NB_FX/.git.backup/objects/c0/52da76fef50a504ef6533359b349f2c8aa4fe6 new file mode 100644 index 00000000..83cde6b2 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/c0/52da76fef50a504ef6533359b349f2c8aa4fe6 @@ -0,0 +1,4 @@ +x+)JMU054g040031QK,I,))L*-I-fH[׮;{m9;QH*3R'>=Rfӓij^U_\PZ\Zqe{tD;5W P@Wx]NV35vɃHLI-*gÒ$?O]}?PB$I= ɎYtӌ %j#º7{_Ί֍fā*f +>r(QAy@7ddTB|Eb [{W^yj!FcpWD5L3&P[ +S +עd8k˅ǢR"ϥ->Fxv` \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/c0/578ff54a3cb21d920cee2f818714c96036d4dd b/Packages/NB_FX/.git.backup/objects/c0/578ff54a3cb21d920cee2f818714c96036d4dd new file mode 100644 index 00000000..c44f674d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c0/578ff54a3cb21d920cee2f818714c96036d4dd differ diff --git a/Packages/NB_FX/.git.backup/objects/c0/59dde913c8eb5e9817350d75f0f13740207b74 b/Packages/NB_FX/.git.backup/objects/c0/59dde913c8eb5e9817350d75f0f13740207b74 new file mode 100644 index 00000000..d93ae83c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c0/59dde913c8eb5e9817350d75f0f13740207b74 differ diff --git a/Packages/NB_FX/.git.backup/objects/c0/762093f2db5d2ad05248e283c1d660e421ce9c b/Packages/NB_FX/.git.backup/objects/c0/762093f2db5d2ad05248e283c1d660e421ce9c new file mode 100644 index 00000000..5a15e85f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c0/762093f2db5d2ad05248e283c1d660e421ce9c differ diff --git a/Packages/NB_FX/.git.backup/objects/c1/a106fd6d24e3ad6f520d99eece233dddd0aa15 b/Packages/NB_FX/.git.backup/objects/c1/a106fd6d24e3ad6f520d99eece233dddd0aa15 new file mode 100644 index 00000000..e5d631d5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c1/a106fd6d24e3ad6f520d99eece233dddd0aa15 differ diff --git a/Packages/NB_FX/.git.backup/objects/c1/fa5a2da3e05ec89ac696c9be42ff7e86a1f9a3 b/Packages/NB_FX/.git.backup/objects/c1/fa5a2da3e05ec89ac696c9be42ff7e86a1f9a3 new file mode 100644 index 00000000..3cf82af0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c1/fa5a2da3e05ec89ac696c9be42ff7e86a1f9a3 differ diff --git a/Packages/NB_FX/.git.backup/objects/c3/02800b6576377ddb5f0fd29413f96c35c5789e b/Packages/NB_FX/.git.backup/objects/c3/02800b6576377ddb5f0fd29413f96c35c5789e new file mode 100644 index 00000000..aa101760 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c3/02800b6576377ddb5f0fd29413f96c35c5789e differ diff --git a/Packages/NB_FX/.git.backup/objects/c3/374ad55d6fb60aaf6eb2153b6ced4b7bdc8bbe b/Packages/NB_FX/.git.backup/objects/c3/374ad55d6fb60aaf6eb2153b6ced4b7bdc8bbe new file mode 100644 index 00000000..e2ee6e93 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c3/374ad55d6fb60aaf6eb2153b6ced4b7bdc8bbe differ diff --git a/Packages/NB_FX/.git.backup/objects/c3/3d80fe3d7e426c1e7d6825995af614bb266650 b/Packages/NB_FX/.git.backup/objects/c3/3d80fe3d7e426c1e7d6825995af614bb266650 new file mode 100644 index 00000000..3d2d8a5c --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/c3/3d80fe3d7e426c1e7d6825995af614bb266650 @@ -0,0 +1,2 @@ +x 1=܅%o@VfYYj `b=].<iL\1g2Ɩy@+OFr2*/4}*3l4hܵ%lMe;h]WGiw&)<ߒ哃L&"YhUct`@Sn6:f؄z*h*[N'&ni"E 4 m7L3lr׌aMHx{\3Sv0 WU;յ MbKϞJ~+un\krq~y{׿/7Exm9JY6I@H FZ{^w*LkbmT3lX'IHT벣mz +{ {r n?feKltaK5S%;dml*@dR|;s7p:0M5RztEuq[$Ʈt%]SԎqrvvqFn GHLXa2 BՆ{}TD(7G0 <Ѩ:0,^SVJ(gg6AOmFA]0:- +nADS%Lܙ;8 \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/c9/9774e37f3796362ab73a04621ca058fab49b3a b/Packages/NB_FX/.git.backup/objects/c9/9774e37f3796362ab73a04621ca058fab49b3a new file mode 100644 index 00000000..de7f0282 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c9/9774e37f3796362ab73a04621ca058fab49b3a differ diff --git a/Packages/NB_FX/.git.backup/objects/c9/af77e48db8f00c6546d22d21bda906d6563354 b/Packages/NB_FX/.git.backup/objects/c9/af77e48db8f00c6546d22d21bda906d6563354 new file mode 100644 index 00000000..fd469a57 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c9/af77e48db8f00c6546d22d21bda906d6563354 differ diff --git a/Packages/NB_FX/.git.backup/objects/c9/d0c804237f5b65c580848f288050ef85295f28 b/Packages/NB_FX/.git.backup/objects/c9/d0c804237f5b65c580848f288050ef85295f28 new file mode 100644 index 00000000..7ec47d17 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/c9/d0c804237f5b65c580848f288050ef85295f28 differ diff --git a/Packages/NB_FX/.git.backup/objects/ca/64fda5d37f28202921ce343a0724f6368f677c b/Packages/NB_FX/.git.backup/objects/ca/64fda5d37f28202921ce343a0724f6368f677c new file mode 100644 index 00000000..610a23de Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ca/64fda5d37f28202921ce343a0724f6368f677c differ diff --git a/Packages/NB_FX/.git.backup/objects/ca/b8382d3ad22c4e3c960b5e90b80dd37e8cc7ce b/Packages/NB_FX/.git.backup/objects/ca/b8382d3ad22c4e3c960b5e90b80dd37e8cc7ce new file mode 100644 index 00000000..7b509fff Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ca/b8382d3ad22c4e3c960b5e90b80dd37e8cc7ce differ diff --git a/Packages/NB_FX/.git.backup/objects/ca/fa661863c1ace111ac972ff5b83fe5e60baf34 b/Packages/NB_FX/.git.backup/objects/ca/fa661863c1ace111ac972ff5b83fe5e60baf34 new file mode 100644 index 00000000..22fc1f95 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ca/fa661863c1ace111ac972ff5b83fe5e60baf34 differ diff --git a/Packages/NB_FX/.git.backup/objects/cb/083ea66cc585838b11ec4e7cf4575460d91f34 b/Packages/NB_FX/.git.backup/objects/cb/083ea66cc585838b11ec4e7cf4575460d91f34 new file mode 100644 index 00000000..e1c82057 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cb/083ea66cc585838b11ec4e7cf4575460d91f34 differ diff --git a/Packages/NB_FX/.git.backup/objects/cb/782235d2a65b4207ff9bf53665f17b325f957e b/Packages/NB_FX/.git.backup/objects/cb/782235d2a65b4207ff9bf53665f17b325f957e new file mode 100644 index 00000000..9eb463a1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cb/782235d2a65b4207ff9bf53665f17b325f957e differ diff --git a/Packages/NB_FX/.git.backup/objects/cb/7e2c8ec3b60167dbfd7a3f8bc30180fc9b82dc b/Packages/NB_FX/.git.backup/objects/cb/7e2c8ec3b60167dbfd7a3f8bc30180fc9b82dc new file mode 100644 index 00000000..c651cb73 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cb/7e2c8ec3b60167dbfd7a3f8bc30180fc9b82dc differ diff --git a/Packages/NB_FX/.git.backup/objects/cb/9e8ae27f7bcf3243486adb1a63f5d69b2c6dc9 b/Packages/NB_FX/.git.backup/objects/cb/9e8ae27f7bcf3243486adb1a63f5d69b2c6dc9 new file mode 100644 index 00000000..545f11a0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cb/9e8ae27f7bcf3243486adb1a63f5d69b2c6dc9 differ diff --git a/Packages/NB_FX/.git.backup/objects/cb/b2302f1c7323e5ae54c20151dfbcf5220fdadc b/Packages/NB_FX/.git.backup/objects/cb/b2302f1c7323e5ae54c20151dfbcf5220fdadc new file mode 100644 index 00000000..c1e67971 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cb/b2302f1c7323e5ae54c20151dfbcf5220fdadc differ diff --git a/Packages/NB_FX/.git.backup/objects/cb/ca9fb4ececeaa1a45da899d5e128442b382ab7 b/Packages/NB_FX/.git.backup/objects/cb/ca9fb4ececeaa1a45da899d5e128442b382ab7 new file mode 100644 index 00000000..72b3b09b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cb/ca9fb4ececeaa1a45da899d5e128442b382ab7 differ diff --git a/Packages/NB_FX/.git.backup/objects/cd/420b14d743394cdee51df8eba8877ab5132a4c b/Packages/NB_FX/.git.backup/objects/cd/420b14d743394cdee51df8eba8877ab5132a4c new file mode 100644 index 00000000..91638c49 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cd/420b14d743394cdee51df8eba8877ab5132a4c differ diff --git a/Packages/NB_FX/.git.backup/objects/cd/817618645d689b8c08cac99247fd808e7b3850 b/Packages/NB_FX/.git.backup/objects/cd/817618645d689b8c08cac99247fd808e7b3850 new file mode 100644 index 00000000..cbf930c9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cd/817618645d689b8c08cac99247fd808e7b3850 differ diff --git a/Packages/NB_FX/.git.backup/objects/cd/b5d655e52142f4e17aaad90c9c0d83967362bd b/Packages/NB_FX/.git.backup/objects/cd/b5d655e52142f4e17aaad90c9c0d83967362bd new file mode 100644 index 00000000..084e25cb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cd/b5d655e52142f4e17aaad90c9c0d83967362bd differ diff --git a/Packages/NB_FX/.git.backup/objects/cd/b6d80f47afebebedb92aaf8076e16c51a7ab29 b/Packages/NB_FX/.git.backup/objects/cd/b6d80f47afebebedb92aaf8076e16c51a7ab29 new file mode 100644 index 00000000..e12f4e4a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cd/b6d80f47afebebedb92aaf8076e16c51a7ab29 differ diff --git a/Packages/NB_FX/.git.backup/objects/cd/d1936ba99b7e082c7e5f4103346f80266cf312 b/Packages/NB_FX/.git.backup/objects/cd/d1936ba99b7e082c7e5f4103346f80266cf312 new file mode 100644 index 00000000..ffa9132f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cd/d1936ba99b7e082c7e5f4103346f80266cf312 differ diff --git a/Packages/NB_FX/.git.backup/objects/ce/5eae3d62270cd6469110f3fd02a1f12958f93b b/Packages/NB_FX/.git.backup/objects/ce/5eae3d62270cd6469110f3fd02a1f12958f93b new file mode 100644 index 00000000..46863290 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ce/5eae3d62270cd6469110f3fd02a1f12958f93b differ diff --git a/Packages/NB_FX/.git.backup/objects/cf/3298a385aa9ca82688d2e16bb0aa0edb29b9b6 b/Packages/NB_FX/.git.backup/objects/cf/3298a385aa9ca82688d2e16bb0aa0edb29b9b6 new file mode 100644 index 00000000..948515ce Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cf/3298a385aa9ca82688d2e16bb0aa0edb29b9b6 differ diff --git a/Packages/NB_FX/.git.backup/objects/cf/3d887400863520b6249d6d46cf12c20f6554b6 b/Packages/NB_FX/.git.backup/objects/cf/3d887400863520b6249d6d46cf12c20f6554b6 new file mode 100644 index 00000000..3aa8f5b0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/cf/3d887400863520b6249d6d46cf12c20f6554b6 differ diff --git a/Packages/NB_FX/.git.backup/objects/d0/8c257d376099f3154a9a8924992084a8029ed6 b/Packages/NB_FX/.git.backup/objects/d0/8c257d376099f3154a9a8924992084a8029ed6 new file mode 100644 index 00000000..ff5d1b9d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d0/8c257d376099f3154a9a8924992084a8029ed6 differ diff --git a/Packages/NB_FX/.git.backup/objects/d1/1d865ad46f560cab16305e9a24db0be845126c b/Packages/NB_FX/.git.backup/objects/d1/1d865ad46f560cab16305e9a24db0be845126c new file mode 100644 index 00000000..3f5f20bd Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d1/1d865ad46f560cab16305e9a24db0be845126c differ diff --git a/Packages/NB_FX/.git.backup/objects/d1/26f24cc49142c0e68facd65741933c33a4cc1c b/Packages/NB_FX/.git.backup/objects/d1/26f24cc49142c0e68facd65741933c33a4cc1c new file mode 100644 index 00000000..dc6cd142 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d1/26f24cc49142c0e68facd65741933c33a4cc1c differ diff --git a/Packages/NB_FX/.git.backup/objects/d1/ac2f68c1218ac57b72d61e8fdeb822df0bb125 b/Packages/NB_FX/.git.backup/objects/d1/ac2f68c1218ac57b72d61e8fdeb822df0bb125 new file mode 100644 index 00000000..40230799 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/d1/ac2f68c1218ac57b72d61e8fdeb822df0bb125 @@ -0,0 +1,3 @@ +xNJ0ܧ](ID|K"ݺ<DAЃEPכxX\۷+g]N"֪$h`Z%S&:4QdTJ3J`J3)X) + +M=Q1 T$88%گa<՞hCۚLB]䛈p柰(h {0 ! cdֵ6Lwba/Ovjٷ'?ݹ;k0;ގmֶd9 ~yr \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/d2/376dec2872950c6e167711f30aca269cf67fad b/Packages/NB_FX/.git.backup/objects/d2/376dec2872950c6e167711f30aca269cf67fad new file mode 100644 index 00000000..12c39db3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d2/376dec2872950c6e167711f30aca269cf67fad differ diff --git a/Packages/NB_FX/.git.backup/objects/d2/b25c7c5dbb8e74d677a2d317cc01799c94e94c b/Packages/NB_FX/.git.backup/objects/d2/b25c7c5dbb8e74d677a2d317cc01799c94e94c new file mode 100644 index 00000000..6f7a21a7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d2/b25c7c5dbb8e74d677a2d317cc01799c94e94c differ diff --git a/Packages/NB_FX/.git.backup/objects/d2/c821dfde74614fa852d987b6e190f08580d9fb b/Packages/NB_FX/.git.backup/objects/d2/c821dfde74614fa852d987b6e190f08580d9fb new file mode 100644 index 00000000..5b6b76a3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d2/c821dfde74614fa852d987b6e190f08580d9fb differ diff --git a/Packages/NB_FX/.git.backup/objects/d2/dafa01adbbc7d5517919332d6f4a02c7e70c6a b/Packages/NB_FX/.git.backup/objects/d2/dafa01adbbc7d5517919332d6f4a02c7e70c6a new file mode 100644 index 00000000..583585ec Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d2/dafa01adbbc7d5517919332d6f4a02c7e70c6a differ diff --git a/Packages/NB_FX/.git.backup/objects/d3/7ce13d103d3d4d06e461fce582fc7107be78c5 b/Packages/NB_FX/.git.backup/objects/d3/7ce13d103d3d4d06e461fce582fc7107be78c5 new file mode 100644 index 00000000..52441a86 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d3/7ce13d103d3d4d06e461fce582fc7107be78c5 differ diff --git a/Packages/NB_FX/.git.backup/objects/d3/a7ae8c3eabdd569bfbb4e34463ceaac7c477f6 b/Packages/NB_FX/.git.backup/objects/d3/a7ae8c3eabdd569bfbb4e34463ceaac7c477f6 new file mode 100644 index 00000000..856c41c2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d3/a7ae8c3eabdd569bfbb4e34463ceaac7c477f6 differ diff --git a/Packages/NB_FX/.git.backup/objects/d4/4184b223a0a10b6a5d03d14da5d1104c2febc1 b/Packages/NB_FX/.git.backup/objects/d4/4184b223a0a10b6a5d03d14da5d1104c2febc1 new file mode 100644 index 00000000..edc0559a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d4/4184b223a0a10b6a5d03d14da5d1104c2febc1 differ diff --git a/Packages/NB_FX/.git.backup/objects/d4/8f93f7c058d21d9f6e11966361e76c87438562 b/Packages/NB_FX/.git.backup/objects/d4/8f93f7c058d21d9f6e11966361e76c87438562 new file mode 100644 index 00000000..1b3b6716 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d4/8f93f7c058d21d9f6e11966361e76c87438562 differ diff --git a/Packages/NB_FX/.git.backup/objects/d6/12ce55df576dbd897731c72c4c5623af0f09e9 b/Packages/NB_FX/.git.backup/objects/d6/12ce55df576dbd897731c72c4c5623af0f09e9 new file mode 100644 index 00000000..85b06ae3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d6/12ce55df576dbd897731c72c4c5623af0f09e9 differ diff --git a/Packages/NB_FX/.git.backup/objects/d6/568d350c97b73b56f44c4e110c9c63f7e8b124 b/Packages/NB_FX/.git.backup/objects/d6/568d350c97b73b56f44c4e110c9c63f7e8b124 new file mode 100644 index 00000000..f1139ce2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d6/568d350c97b73b56f44c4e110c9c63f7e8b124 differ diff --git a/Packages/NB_FX/.git.backup/objects/d6/b555ab377bbae3f84b115e054bb61fec016b95 b/Packages/NB_FX/.git.backup/objects/d6/b555ab377bbae3f84b115e054bb61fec016b95 new file mode 100644 index 00000000..b817af6f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d6/b555ab377bbae3f84b115e054bb61fec016b95 differ diff --git a/Packages/NB_FX/.git.backup/objects/d6/f2912f44cbf3d52d9836a8a582d89556a108cd b/Packages/NB_FX/.git.backup/objects/d6/f2912f44cbf3d52d9836a8a582d89556a108cd new file mode 100644 index 00000000..ede79ba4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d6/f2912f44cbf3d52d9836a8a582d89556a108cd differ diff --git a/Packages/NB_FX/.git.backup/objects/d7/8e1776b86d3a6a4b9c011c56a7cda21b53fbbb b/Packages/NB_FX/.git.backup/objects/d7/8e1776b86d3a6a4b9c011c56a7cda21b53fbbb new file mode 100644 index 00000000..594a118c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d7/8e1776b86d3a6a4b9c011c56a7cda21b53fbbb differ diff --git a/Packages/NB_FX/.git.backup/objects/d7/9161e5c2f82ac062033cf07b5df0ef0da89880 b/Packages/NB_FX/.git.backup/objects/d7/9161e5c2f82ac062033cf07b5df0ef0da89880 new file mode 100644 index 00000000..96cb91a3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d7/9161e5c2f82ac062033cf07b5df0ef0da89880 differ diff --git a/Packages/NB_FX/.git.backup/objects/d7/bee30f8f23c2536f19cb0156f776e075d4f625 b/Packages/NB_FX/.git.backup/objects/d7/bee30f8f23c2536f19cb0156f776e075d4f625 new file mode 100644 index 00000000..f2be37eb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d7/bee30f8f23c2536f19cb0156f776e075d4f625 differ diff --git a/Packages/NB_FX/.git.backup/objects/d8/13d001310d79a62529924e8ca12a22e60eb28d b/Packages/NB_FX/.git.backup/objects/d8/13d001310d79a62529924e8ca12a22e60eb28d new file mode 100644 index 00000000..9b7896ad --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/d8/13d001310d79a62529924e8ca12a22e60eb28d @@ -0,0 +1,2 @@ +xJ1])$w7_%su1;f"ؖDTmpgoc>y`׶7Z[)6P]XpFXV7,=M:UU%ZT:ё7tx&]? 9ҁ6\fصW +-?,|/пE?^tߛ[i~O}zOe|^V_ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/d8/23fb50d531303d26a63483509a65c1d45f4ef1 b/Packages/NB_FX/.git.backup/objects/d8/23fb50d531303d26a63483509a65c1d45f4ef1 new file mode 100644 index 00000000..8a0f5dc5 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d8/23fb50d531303d26a63483509a65c1d45f4ef1 differ diff --git a/Packages/NB_FX/.git.backup/objects/d9/b95998738c8b1424d70f78f23572866ff531ec b/Packages/NB_FX/.git.backup/objects/d9/b95998738c8b1424d70f78f23572866ff531ec new file mode 100644 index 00000000..f6dc8dc1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/d9/b95998738c8b1424d70f78f23572866ff531ec differ diff --git a/Packages/NB_FX/.git.backup/objects/da/fddeb92684e51b22855419d2542a2be8aca154 b/Packages/NB_FX/.git.backup/objects/da/fddeb92684e51b22855419d2542a2be8aca154 new file mode 100644 index 00000000..8b61c836 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/da/fddeb92684e51b22855419d2542a2be8aca154 differ diff --git a/Packages/NB_FX/.git.backup/objects/db/98dba5639913f3b06a394ac98ae44bc297c906 b/Packages/NB_FX/.git.backup/objects/db/98dba5639913f3b06a394ac98ae44bc297c906 new file mode 100644 index 00000000..457ff50c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/db/98dba5639913f3b06a394ac98ae44bc297c906 differ diff --git a/Packages/NB_FX/.git.backup/objects/dc/34f3d7ebd63eb994bc3001663559b0241a3c06 b/Packages/NB_FX/.git.backup/objects/dc/34f3d7ebd63eb994bc3001663559b0241a3c06 new file mode 100644 index 00000000..bb0efa73 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/dc/34f3d7ebd63eb994bc3001663559b0241a3c06 differ diff --git a/Packages/NB_FX/.git.backup/objects/dc/bfb5049641429acb72f031b9a78177221b62cb b/Packages/NB_FX/.git.backup/objects/dc/bfb5049641429acb72f031b9a78177221b62cb new file mode 100644 index 00000000..6456b9bf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/dc/bfb5049641429acb72f031b9a78177221b62cb differ diff --git a/Packages/NB_FX/.git.backup/objects/dc/d4e058f8ca62c2677143b12c6c394f09950956 b/Packages/NB_FX/.git.backup/objects/dc/d4e058f8ca62c2677143b12c6c394f09950956 new file mode 100644 index 00000000..70c4246a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/dc/d4e058f8ca62c2677143b12c6c394f09950956 differ diff --git a/Packages/NB_FX/.git.backup/objects/dd/2b8d0712d7875606ae00b90942a8173859b667 b/Packages/NB_FX/.git.backup/objects/dd/2b8d0712d7875606ae00b90942a8173859b667 new file mode 100644 index 00000000..d14f5cec --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/dd/2b8d0712d7875606ae00b90942a8173859b667 @@ -0,0 +1,2 @@ +xu +0E]+K.|х4cHҴHޱuu9˝>j(repUҚ~pG0MŴeTYI(]0L.B٠[?è^s0RvusuSRJ| \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/dd/f63f942a12470348236528bd3ecfae859dd994 b/Packages/NB_FX/.git.backup/objects/dd/f63f942a12470348236528bd3ecfae859dd994 new file mode 100644 index 00000000..bac820a0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/dd/f63f942a12470348236528bd3ecfae859dd994 differ diff --git a/Packages/NB_FX/.git.backup/objects/de/293b0244dcf55fcd5e3bc79a609482d4250565 b/Packages/NB_FX/.git.backup/objects/de/293b0244dcf55fcd5e3bc79a609482d4250565 new file mode 100644 index 00000000..2cdee105 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/de/293b0244dcf55fcd5e3bc79a609482d4250565 differ diff --git a/Packages/NB_FX/.git.backup/objects/de/f3f250a882654b3600cc96368a35e042e41a42 b/Packages/NB_FX/.git.backup/objects/de/f3f250a882654b3600cc96368a35e042e41a42 new file mode 100644 index 00000000..2cbed1cf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/de/f3f250a882654b3600cc96368a35e042e41a42 differ diff --git a/Packages/NB_FX/.git.backup/objects/e0/458ebe92c4fb3cb3ed3f959c0d3fcd41de5289 b/Packages/NB_FX/.git.backup/objects/e0/458ebe92c4fb3cb3ed3f959c0d3fcd41de5289 new file mode 100644 index 00000000..d89618e7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e0/458ebe92c4fb3cb3ed3f959c0d3fcd41de5289 differ diff --git a/Packages/NB_FX/.git.backup/objects/e0/821613858636cf3c9573ecdd4316f893ff8a80 b/Packages/NB_FX/.git.backup/objects/e0/821613858636cf3c9573ecdd4316f893ff8a80 new file mode 100644 index 00000000..3ade3be2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e0/821613858636cf3c9573ecdd4316f893ff8a80 differ diff --git a/Packages/NB_FX/.git.backup/objects/e0/87542c39d6477f885fab6eaad3ae12f72c43e4 b/Packages/NB_FX/.git.backup/objects/e0/87542c39d6477f885fab6eaad3ae12f72c43e4 new file mode 100644 index 00000000..932bdf84 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/e0/87542c39d6477f885fab6eaad3ae12f72c43e4 @@ -0,0 +1,4 @@ +xVn8gBFؾ,zucӴnEams! w"%R^P=84<3s̑B-˗0\nh,{(!r%Mv$|u>(#n^Ϸ4gQr{ |0]1̯4VQ[hvL LK*Y jLu4٨J_7Ŝ`V[*7,?bf@t;sD8Q\Dw]E֎h$ +¦Bu$T0/&ə/7J榳i$~:GtrZZ#ϞEA+j@J}plY9+Kf/2%FFnjaA P=)ƠbinmSM?tn@#~ԡ/SB{kutϒqA`.OPBؠqPɄKඡQ`) 1c~ d(kkv+$PM|Y-[QE2䊩$, +.@]k|Y ac :xU&OVxܵ$xq^57 TMvK>gvn!Ř${oSn\;xy">]%RmGZ +;Q@Lߓi848.WOۻin[86_9kuT]p܁i0#{c,M&Av}rrr6mӇ=&O񛁆Y~YbSIM0pٕ(rNJB$o$IBzbgx=Ejٔèa]NhٻP^XJkbzs~#к͌[/?* +nr6,\RWZ3|ES[nPamH Od \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/e0/98ccdad1462800a9501fc611f7c00a4c10c29a b/Packages/NB_FX/.git.backup/objects/e0/98ccdad1462800a9501fc611f7c00a4c10c29a new file mode 100644 index 00000000..585617d9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e0/98ccdad1462800a9501fc611f7c00a4c10c29a differ diff --git a/Packages/NB_FX/.git.backup/objects/e0/cc8ad333793480e73f7f0c1b6568ab44d4fe4c b/Packages/NB_FX/.git.backup/objects/e0/cc8ad333793480e73f7f0c1b6568ab44d4fe4c new file mode 100644 index 00000000..e2f2ddae Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e0/cc8ad333793480e73f7f0c1b6568ab44d4fe4c differ diff --git a/Packages/NB_FX/.git.backup/objects/e0/da04ca8906b3a738c33338aaebfee6ab287a74 b/Packages/NB_FX/.git.backup/objects/e0/da04ca8906b3a738c33338aaebfee6ab287a74 new file mode 100644 index 00000000..a73cae69 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e0/da04ca8906b3a738c33338aaebfee6ab287a74 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/114b6004e7876da31579f99cea1fa9fca511a1 b/Packages/NB_FX/.git.backup/objects/e1/114b6004e7876da31579f99cea1fa9fca511a1 new file mode 100644 index 00000000..b060f2d4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e1/114b6004e7876da31579f99cea1fa9fca511a1 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/17f2ab772998ab18ede3402b0088e98bb89e51 b/Packages/NB_FX/.git.backup/objects/e1/17f2ab772998ab18ede3402b0088e98bb89e51 new file mode 100644 index 00000000..91b23a12 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e1/17f2ab772998ab18ede3402b0088e98bb89e51 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/396dda180e8f62a079d1fff541c17c03ac7246 b/Packages/NB_FX/.git.backup/objects/e1/396dda180e8f62a079d1fff541c17c03ac7246 new file mode 100644 index 00000000..d5e4baeb Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e1/396dda180e8f62a079d1fff541c17c03ac7246 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/3e358cf1bb1d1849c5cfb7a5e2b73ba5eb8517 b/Packages/NB_FX/.git.backup/objects/e1/3e358cf1bb1d1849c5cfb7a5e2b73ba5eb8517 new file mode 100644 index 00000000..590d4d27 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e1/3e358cf1bb1d1849c5cfb7a5e2b73ba5eb8517 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/8c0e315d44a4546b470bc4377bce94c8bf3658 b/Packages/NB_FX/.git.backup/objects/e1/8c0e315d44a4546b470bc4377bce94c8bf3658 new file mode 100644 index 00000000..4251b422 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e1/8c0e315d44a4546b470bc4377bce94c8bf3658 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/a6491f6952ef1e8d8cc3b99ae0c47719b28dd5 b/Packages/NB_FX/.git.backup/objects/e1/a6491f6952ef1e8d8cc3b99ae0c47719b28dd5 new file mode 100644 index 00000000..9a1ed14c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e1/a6491f6952ef1e8d8cc3b99ae0c47719b28dd5 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/c0ae0dccc1535d6155a5b2566da740848ae944 b/Packages/NB_FX/.git.backup/objects/e1/c0ae0dccc1535d6155a5b2566da740848ae944 new file mode 100644 index 00000000..ea35e3d8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e1/c0ae0dccc1535d6155a5b2566da740848ae944 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/c56413e42c953e8d06f77b8867c98883deb307 b/Packages/NB_FX/.git.backup/objects/e1/c56413e42c953e8d06f77b8867c98883deb307 new file mode 100644 index 00000000..b9dd82e0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e1/c56413e42c953e8d06f77b8867c98883deb307 differ diff --git a/Packages/NB_FX/.git.backup/objects/e1/f2c7743e69021d0767e1f9c6d0bac85bec6c5d b/Packages/NB_FX/.git.backup/objects/e1/f2c7743e69021d0767e1f9c6d0bac85bec6c5d new file mode 100644 index 00000000..db9d848f --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/e1/f2c7743e69021d0767e1f9c6d0bac85bec6c5d @@ -0,0 +1,6 @@ +x+)JMU016g040031Qs +/. (ON-.KM-Idpʸ~=:"KV횫`gP>(;T%J߼< 7;8#1%b K\>w0C +wP}7|(7RuM3gdy I|9+& [7qF { +P"J@8(5В̜̒J1HLpat+/?Xͺ`9hf]x#{cS?P[ +S +עd8k˅ǢR"ϥ->Fxv`o! \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/e1/f5260d52270339eaffcc8f8616f3809d5ae1eb b/Packages/NB_FX/.git.backup/objects/e1/f5260d52270339eaffcc8f8616f3809d5ae1eb new file mode 100644 index 00000000..58356e0f --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/e1/f5260d52270339eaffcc8f8616f3809d5ae1eb @@ -0,0 +1,3 @@ +x+)JMU02`040031QpM,/M-IdX.t ^?^z|a}Q b +x^FW'DvB *+M^MOnӅYte1U/Ҟl['=h4jRpFbJ*EY2s2dq *vci +W,̝RX\ \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/e2/7d0f566e9cdfce8c842ea7b95ae81f450d239c b/Packages/NB_FX/.git.backup/objects/e2/7d0f566e9cdfce8c842ea7b95ae81f450d239c new file mode 100644 index 00000000..c252cfa8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e2/7d0f566e9cdfce8c842ea7b95ae81f450d239c differ diff --git a/Packages/NB_FX/.git.backup/objects/e2/bb6bc6867ec60b4c2b39a912efe8136b525846 b/Packages/NB_FX/.git.backup/objects/e2/bb6bc6867ec60b4c2b39a912efe8136b525846 new file mode 100644 index 00000000..b70d3a7c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e2/bb6bc6867ec60b4c2b39a912efe8136b525846 differ diff --git a/Packages/NB_FX/.git.backup/objects/e3/1724a6f68e600c7310f56f0828910ac503194e b/Packages/NB_FX/.git.backup/objects/e3/1724a6f68e600c7310f56f0828910ac503194e new file mode 100644 index 00000000..394d43dd Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e3/1724a6f68e600c7310f56f0828910ac503194e differ diff --git a/Packages/NB_FX/.git.backup/objects/e3/2571cb8fca03d12b6e4449c9afdca0c34a344f b/Packages/NB_FX/.git.backup/objects/e3/2571cb8fca03d12b6e4449c9afdca0c34a344f new file mode 100644 index 00000000..9b1653a5 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/e3/2571cb8fca03d12b6e4449c9afdca0c34a344f @@ -0,0 +1,2 @@ +xOKQ[ϧ"3cDu<߼Ǒ\ +E.EA!!-bX~׸+4%A*˹c|>뀦K9p2QaZf :VMR̈kaL%Jڼgn4 T0G![XGZu2EjUZdF ЀU.GX1 0 Da)9AEdk˅t%C-n+ׁT"Im'r ۼѐ/޸%'ہd8<ϯۊAAݔP3'N+|@Ǵ~ToN-[]yz-  \X7t/P 'j'"ar \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/e3/8346e949471ec6c02ebcc53795a259b9484bdd b/Packages/NB_FX/.git.backup/objects/e3/8346e949471ec6c02ebcc53795a259b9484bdd new file mode 100644 index 00000000..dde3c48a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e3/8346e949471ec6c02ebcc53795a259b9484bdd differ diff --git a/Packages/NB_FX/.git.backup/objects/e3/9cfba9c66144b5963dd67c955da4e0d94d9fa1 b/Packages/NB_FX/.git.backup/objects/e3/9cfba9c66144b5963dd67c955da4e0d94d9fa1 new file mode 100644 index 00000000..d5c719e9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e3/9cfba9c66144b5963dd67c955da4e0d94d9fa1 differ diff --git a/Packages/NB_FX/.git.backup/objects/e3/d747627b688284993eb13e819ac282d37bfe1d b/Packages/NB_FX/.git.backup/objects/e3/d747627b688284993eb13e819ac282d37bfe1d new file mode 100644 index 00000000..6a0b5907 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e3/d747627b688284993eb13e819ac282d37bfe1d differ diff --git a/Packages/NB_FX/.git.backup/objects/e3/e436bc8dd9827cd97fb0e6c92b3a12c78de895 b/Packages/NB_FX/.git.backup/objects/e3/e436bc8dd9827cd97fb0e6c92b3a12c78de895 new file mode 100644 index 00000000..76e09000 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e3/e436bc8dd9827cd97fb0e6c92b3a12c78de895 differ diff --git a/Packages/NB_FX/.git.backup/objects/e4/284ecf523dfb9872bd624c173a34c904d338bd b/Packages/NB_FX/.git.backup/objects/e4/284ecf523dfb9872bd624c173a34c904d338bd new file mode 100644 index 00000000..3e09f76a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e4/284ecf523dfb9872bd624c173a34c904d338bd differ diff --git a/Packages/NB_FX/.git.backup/objects/e4/8cbbe9c7dd983c1224e77540613da7d033f9d1 b/Packages/NB_FX/.git.backup/objects/e4/8cbbe9c7dd983c1224e77540613da7d033f9d1 new file mode 100644 index 00000000..65b19983 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e4/8cbbe9c7dd983c1224e77540613da7d033f9d1 differ diff --git a/Packages/NB_FX/.git.backup/objects/e5/65c7c37a763f1eb94a2a42786f49847d065448 b/Packages/NB_FX/.git.backup/objects/e5/65c7c37a763f1eb94a2a42786f49847d065448 new file mode 100644 index 00000000..4ef97eff Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e5/65c7c37a763f1eb94a2a42786f49847d065448 differ diff --git a/Packages/NB_FX/.git.backup/objects/e5/8c513b5276c8efb465148f3ba553aa32fe96b1 b/Packages/NB_FX/.git.backup/objects/e5/8c513b5276c8efb465148f3ba553aa32fe96b1 new file mode 100644 index 00000000..bd6a961d --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/e5/8c513b5276c8efb465148f3ba553aa32fe96b1 @@ -0,0 +1,3 @@ +x+)JMU017e040031QK,L/JePHFNO^{TS@~qI@Q~rjqqf^^njI"{T=Yޯl\M @]=Ch/'ڹw/\8C\nvpFbJjQ1=|8%!tQ}aB2ٙqiئ2k@7b];/{'嬘/lh1|_f3{Ϳ3LO(dC͋(M<CK2s2K*!FV"1…ӽN`5jbX\ұ,镓ޝ]#iLP[ +S +עd8k˅ǢR"ϥ->Fxv`* \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/e5/ebfeec7d323945179c6af816f54defabc86111 b/Packages/NB_FX/.git.backup/objects/e5/ebfeec7d323945179c6af816f54defabc86111 new file mode 100644 index 00000000..4dbc40b6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e5/ebfeec7d323945179c6af816f54defabc86111 differ diff --git a/Packages/NB_FX/.git.backup/objects/e6/71fa61333796267d18de55805a067b6018b99b b/Packages/NB_FX/.git.backup/objects/e6/71fa61333796267d18de55805a067b6018b99b new file mode 100644 index 00000000..85f5f094 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e6/71fa61333796267d18de55805a067b6018b99b differ diff --git a/Packages/NB_FX/.git.backup/objects/e7/087e520a5d17500ec2528bd7c871777d4fbf5c b/Packages/NB_FX/.git.backup/objects/e7/087e520a5d17500ec2528bd7c871777d4fbf5c new file mode 100644 index 00000000..3d479e16 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/e7/087e520a5d17500ec2528bd7c871777d4fbf5c @@ -0,0 +1,4 @@ +xӱ +0`>E-AQ(" sIiN"O$rffR 8w& +39FNҌ,(Rzpm (H 2諌1]tz7mD?? ;6N \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/e7/3409adf624d88d850739d9764ac11eed5c163f b/Packages/NB_FX/.git.backup/objects/e7/3409adf624d88d850739d9764ac11eed5c163f new file mode 100644 index 00000000..53899c01 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e7/3409adf624d88d850739d9764ac11eed5c163f differ diff --git a/Packages/NB_FX/.git.backup/objects/e7/4655fef0d66eba714c6530512351c0e0bab456 b/Packages/NB_FX/.git.backup/objects/e7/4655fef0d66eba714c6530512351c0e0bab456 new file mode 100644 index 00000000..fc8a856c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e7/4655fef0d66eba714c6530512351c0e0bab456 differ diff --git a/Packages/NB_FX/.git.backup/objects/e7/64cdc9c8a49c2b760ac10c7fd02c9453f794ca b/Packages/NB_FX/.git.backup/objects/e7/64cdc9c8a49c2b760ac10c7fd02c9453f794ca new file mode 100644 index 00000000..a43b0bf6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e7/64cdc9c8a49c2b760ac10c7fd02c9453f794ca differ diff --git a/Packages/NB_FX/.git.backup/objects/e8/3420000afc5bdcf7084e5d1f288dbbdb772570 b/Packages/NB_FX/.git.backup/objects/e8/3420000afc5bdcf7084e5d1f288dbbdb772570 new file mode 100644 index 00000000..e30447af Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e8/3420000afc5bdcf7084e5d1f288dbbdb772570 differ diff --git a/Packages/NB_FX/.git.backup/objects/e8/9c9bbe94b25c3e7f035bed7a8aad256b92db13 b/Packages/NB_FX/.git.backup/objects/e8/9c9bbe94b25c3e7f035bed7a8aad256b92db13 new file mode 100644 index 00000000..995ea492 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e8/9c9bbe94b25c3e7f035bed7a8aad256b92db13 differ diff --git a/Packages/NB_FX/.git.backup/objects/e8/ace915f8d8b7361f71287aa1c3d48aaa1ccc23 b/Packages/NB_FX/.git.backup/objects/e8/ace915f8d8b7361f71287aa1c3d48aaa1ccc23 new file mode 100644 index 00000000..35d708d7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e8/ace915f8d8b7361f71287aa1c3d48aaa1ccc23 differ diff --git a/Packages/NB_FX/.git.backup/objects/e9/0a028bfa6cf8269edad7410ebe1cef4a3ba7ca b/Packages/NB_FX/.git.backup/objects/e9/0a028bfa6cf8269edad7410ebe1cef4a3ba7ca new file mode 100644 index 00000000..18c9690d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e9/0a028bfa6cf8269edad7410ebe1cef4a3ba7ca differ diff --git a/Packages/NB_FX/.git.backup/objects/e9/a320b3c8a38748cb4a339c204bac8534fc695b b/Packages/NB_FX/.git.backup/objects/e9/a320b3c8a38748cb4a339c204bac8534fc695b new file mode 100644 index 00000000..b3c7e3b7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e9/a320b3c8a38748cb4a339c204bac8534fc695b differ diff --git a/Packages/NB_FX/.git.backup/objects/e9/d4f2b5c2a581b0a00565c527199c34e60215a9 b/Packages/NB_FX/.git.backup/objects/e9/d4f2b5c2a581b0a00565c527199c34e60215a9 new file mode 100644 index 00000000..bf0a8744 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/e9/d4f2b5c2a581b0a00565c527199c34e60215a9 differ diff --git a/Packages/NB_FX/.git.backup/objects/ea/da4e48f4f1209151cadbf7c28e4009a2c6913b b/Packages/NB_FX/.git.backup/objects/ea/da4e48f4f1209151cadbf7c28e4009a2c6913b new file mode 100644 index 00000000..27ac97e4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ea/da4e48f4f1209151cadbf7c28e4009a2c6913b differ diff --git a/Packages/NB_FX/.git.backup/objects/eb/9e15fa7ca0324b91fc7b82bc74094f2ffae978 b/Packages/NB_FX/.git.backup/objects/eb/9e15fa7ca0324b91fc7b82bc74094f2ffae978 new file mode 100644 index 00000000..cffaf9d2 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/eb/9e15fa7ca0324b91fc7b82bc74094f2ffae978 differ diff --git a/Packages/NB_FX/.git.backup/objects/eb/9fe9d419d5b254416fb682c43c74235d515aff b/Packages/NB_FX/.git.backup/objects/eb/9fe9d419d5b254416fb682c43c74235d515aff new file mode 100644 index 00000000..53d2311d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/eb/9fe9d419d5b254416fb682c43c74235d515aff differ diff --git a/Packages/NB_FX/.git.backup/objects/eb/b861635e73933048f379a46939a9f11a564513 b/Packages/NB_FX/.git.backup/objects/eb/b861635e73933048f379a46939a9f11a564513 new file mode 100644 index 00000000..edf004cf Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/eb/b861635e73933048f379a46939a9f11a564513 differ diff --git a/Packages/NB_FX/.git.backup/objects/eb/ded3ed981dbb26bd5c1c966708e9794d87b498 b/Packages/NB_FX/.git.backup/objects/eb/ded3ed981dbb26bd5c1c966708e9794d87b498 new file mode 100644 index 00000000..7e3819dc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/eb/ded3ed981dbb26bd5c1c966708e9794d87b498 differ diff --git a/Packages/NB_FX/.git.backup/objects/ec/36ef6491d26d378e271bc020e428cf951829dc b/Packages/NB_FX/.git.backup/objects/ec/36ef6491d26d378e271bc020e428cf951829dc new file mode 100644 index 00000000..52aa8375 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ec/36ef6491d26d378e271bc020e428cf951829dc differ diff --git a/Packages/NB_FX/.git.backup/objects/ec/8408a9221f14b0661d3653215cd04453d77247 b/Packages/NB_FX/.git.backup/objects/ec/8408a9221f14b0661d3653215cd04453d77247 new file mode 100644 index 00000000..c6a03cc9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ec/8408a9221f14b0661d3653215cd04453d77247 differ diff --git a/Packages/NB_FX/.git.backup/objects/ed/169c6a4caf24cbab25cef5299e300157bcdc52 b/Packages/NB_FX/.git.backup/objects/ed/169c6a4caf24cbab25cef5299e300157bcdc52 new file mode 100644 index 00000000..3558dc8e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ed/169c6a4caf24cbab25cef5299e300157bcdc52 differ diff --git a/Packages/NB_FX/.git.backup/objects/ed/99b3e9a580d75a2d76db2c1b0d0b316701d9bf b/Packages/NB_FX/.git.backup/objects/ed/99b3e9a580d75a2d76db2c1b0d0b316701d9bf new file mode 100644 index 00000000..e25b80f9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ed/99b3e9a580d75a2d76db2c1b0d0b316701d9bf differ diff --git a/Packages/NB_FX/.git.backup/objects/ee/069456e6cbeb27660c7a8a4f87f58044d7026c b/Packages/NB_FX/.git.backup/objects/ee/069456e6cbeb27660c7a8a4f87f58044d7026c new file mode 100644 index 00000000..4f9153b9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ee/069456e6cbeb27660c7a8a4f87f58044d7026c differ diff --git a/Packages/NB_FX/.git.backup/objects/ee/26c55dc0b55a14d06d3840a49da6c829246082 b/Packages/NB_FX/.git.backup/objects/ee/26c55dc0b55a14d06d3840a49da6c829246082 new file mode 100644 index 00000000..7c89c1d7 --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/ee/26c55dc0b55a14d06d3840a49da6c829246082 @@ -0,0 +1,2 @@ +xM1gSd/H^:0G t722" C^t= ]/bA[b8ǘuG +-2=d}7 \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/ef/cfb887e56250b5926474f0d4203e3ad2baef89 b/Packages/NB_FX/.git.backup/objects/ef/cfb887e56250b5926474f0d4203e3ad2baef89 new file mode 100644 index 00000000..8df43186 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ef/cfb887e56250b5926474f0d4203e3ad2baef89 differ diff --git a/Packages/NB_FX/.git.backup/objects/f0/2754c3438ca1eadd8dc69d93253bbbebbb5e54 b/Packages/NB_FX/.git.backup/objects/f0/2754c3438ca1eadd8dc69d93253bbbebbb5e54 new file mode 100644 index 00000000..04839138 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f0/2754c3438ca1eadd8dc69d93253bbbebbb5e54 differ diff --git a/Packages/NB_FX/.git.backup/objects/f0/70484a62aa416fc1f86ba70093992ad5ab1235 b/Packages/NB_FX/.git.backup/objects/f0/70484a62aa416fc1f86ba70093992ad5ab1235 new file mode 100644 index 00000000..cbe9a77a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f0/70484a62aa416fc1f86ba70093992ad5ab1235 differ diff --git a/Packages/NB_FX/.git.backup/objects/f0/f847d2ed61f5ae0668ab3b442396af3e3aebe1 b/Packages/NB_FX/.git.backup/objects/f0/f847d2ed61f5ae0668ab3b442396af3e3aebe1 new file mode 100644 index 00000000..badc8462 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f0/f847d2ed61f5ae0668ab3b442396af3e3aebe1 differ diff --git a/Packages/NB_FX/.git.backup/objects/f1/4d03fd8b059435f3f7a9df08e7675b7fc04844 b/Packages/NB_FX/.git.backup/objects/f1/4d03fd8b059435f3f7a9df08e7675b7fc04844 new file mode 100644 index 00000000..c444508d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f1/4d03fd8b059435f3f7a9df08e7675b7fc04844 differ diff --git a/Packages/NB_FX/.git.backup/objects/f1/663dd8437fb67968a27434780df56965bf4939 b/Packages/NB_FX/.git.backup/objects/f1/663dd8437fb67968a27434780df56965bf4939 new file mode 100644 index 00000000..c08fadd4 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f1/663dd8437fb67968a27434780df56965bf4939 differ diff --git a/Packages/NB_FX/.git.backup/objects/f2/787740fec5e57485d685d286e2181585cb8702 b/Packages/NB_FX/.git.backup/objects/f2/787740fec5e57485d685d286e2181585cb8702 new file mode 100644 index 00000000..4612f12e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f2/787740fec5e57485d685d286e2181585cb8702 differ diff --git a/Packages/NB_FX/.git.backup/objects/f2/98f85f6745f1f5bd0eb0afe56c9ed02032d7ab b/Packages/NB_FX/.git.backup/objects/f2/98f85f6745f1f5bd0eb0afe56c9ed02032d7ab new file mode 100644 index 00000000..1df71f06 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f2/98f85f6745f1f5bd0eb0afe56c9ed02032d7ab differ diff --git a/Packages/NB_FX/.git.backup/objects/f2/dcac63082fd62a32d728591814d79a958b5105 b/Packages/NB_FX/.git.backup/objects/f2/dcac63082fd62a32d728591814d79a958b5105 new file mode 100644 index 00000000..42b8cb9f --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/f2/dcac63082fd62a32d728591814d79a958b5105 @@ -0,0 +1,4 @@ +x+)JMU002f040031Qp(M,LvLJ-*2RKJR=KRs L/pLM\1.+լZ橏;DXUϼ_`dm 9EN9y)h޸"'[0v] =f]-+-l$$-?Į 3>@5dccv `ُ9~WbһmOGq0=9ehl[+:eWY ,Nǫb419U3W+oVv1 3b=sk{bMԗ"xu@,bZ#7}M4G_%AA}\ZP_TJŠTq"nϛ۶>Ý]X䥯{:h OKW&G>[9am+׼aus^ ][ZY򓴣n,XizH| ^ażN`u#}Xfl +D:nX?WXDL)8UC,8W>@{ܯD댖j,NuKq,.F]K ia=Bu6!4Ba}a\ZU}!O$%$VwWq'fvr?ȿdK*,'^T"z42a] +e_U)QEj=L}%N jFV\u_tY>T[X"z,r{h_)bDx%3p)Vl൦4/̈́aaE%iiũ\SZg+Ly.΋'oIg[ћMgxa \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/f3/2a46c5b0ad8c41c8bdd45ea8b1a79b464446f1 b/Packages/NB_FX/.git.backup/objects/f3/2a46c5b0ad8c41c8bdd45ea8b1a79b464446f1 new file mode 100644 index 00000000..4f768339 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f3/2a46c5b0ad8c41c8bdd45ea8b1a79b464446f1 differ diff --git a/Packages/NB_FX/.git.backup/objects/f3/5630c5f606a115518c261ead91d751a32db52f b/Packages/NB_FX/.git.backup/objects/f3/5630c5f606a115518c261ead91d751a32db52f new file mode 100644 index 00000000..135cc3c3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f3/5630c5f606a115518c261ead91d751a32db52f differ diff --git a/Packages/NB_FX/.git.backup/objects/f4/719f5d90c7c5a8b3cfeec61ea4f456ce336030 b/Packages/NB_FX/.git.backup/objects/f4/719f5d90c7c5a8b3cfeec61ea4f456ce336030 new file mode 100644 index 00000000..bfd729de Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f4/719f5d90c7c5a8b3cfeec61ea4f456ce336030 differ diff --git a/Packages/NB_FX/.git.backup/objects/f4/8d529217b8f39337110149eb09a614f877cb54 b/Packages/NB_FX/.git.backup/objects/f4/8d529217b8f39337110149eb09a614f877cb54 new file mode 100644 index 00000000..19aab14a Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f4/8d529217b8f39337110149eb09a614f877cb54 differ diff --git a/Packages/NB_FX/.git.backup/objects/f5/23cac331d8464e985258bfb9d0de8594e54e37 b/Packages/NB_FX/.git.backup/objects/f5/23cac331d8464e985258bfb9d0de8594e54e37 new file mode 100644 index 00000000..f3eedb47 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f5/23cac331d8464e985258bfb9d0de8594e54e37 differ diff --git a/Packages/NB_FX/.git.backup/objects/f5/67f57039351b3a6db17f460eb343720e3e4b91 b/Packages/NB_FX/.git.backup/objects/f5/67f57039351b3a6db17f460eb343720e3e4b91 new file mode 100644 index 00000000..b49a5a6c --- /dev/null +++ b/Packages/NB_FX/.git.backup/objects/f5/67f57039351b3a6db17f460eb343720e3e4b91 @@ -0,0 +1,2 @@ +x+)JMU02`040031QpM,/M-IdX.t ^?^z|a}Q bLU Pe9WA *+M^MOnӅYte1U/Ҟl['=h4jRpFbJ*EY2s2dq *vci +W,̝+W \ No newline at end of file diff --git a/Packages/NB_FX/.git.backup/objects/f5/6ad3501cc80e5c88281381ea04609ebf22e3ca b/Packages/NB_FX/.git.backup/objects/f5/6ad3501cc80e5c88281381ea04609ebf22e3ca new file mode 100644 index 00000000..380a163f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f5/6ad3501cc80e5c88281381ea04609ebf22e3ca differ diff --git a/Packages/NB_FX/.git.backup/objects/f5/cca66c76b11cee12f8caa21dd3d36962889c6f b/Packages/NB_FX/.git.backup/objects/f5/cca66c76b11cee12f8caa21dd3d36962889c6f new file mode 100644 index 00000000..86f221f9 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f5/cca66c76b11cee12f8caa21dd3d36962889c6f differ diff --git a/Packages/NB_FX/.git.backup/objects/f6/3c9af6aa13f09c68fc1bb046a12fbca65b4d14 b/Packages/NB_FX/.git.backup/objects/f6/3c9af6aa13f09c68fc1bb046a12fbca65b4d14 new file mode 100644 index 00000000..da3149d3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f6/3c9af6aa13f09c68fc1bb046a12fbca65b4d14 differ diff --git a/Packages/NB_FX/.git.backup/objects/f6/4dcfbdfe6618467528ba31e6d5ee584223d8c7 b/Packages/NB_FX/.git.backup/objects/f6/4dcfbdfe6618467528ba31e6d5ee584223d8c7 new file mode 100644 index 00000000..af3335ed Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f6/4dcfbdfe6618467528ba31e6d5ee584223d8c7 differ diff --git a/Packages/NB_FX/.git.backup/objects/f6/5a597e13028229269a50d1d2d4de4e332c2b59 b/Packages/NB_FX/.git.backup/objects/f6/5a597e13028229269a50d1d2d4de4e332c2b59 new file mode 100644 index 00000000..2e2534c0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f6/5a597e13028229269a50d1d2d4de4e332c2b59 differ diff --git a/Packages/NB_FX/.git.backup/objects/f6/7a36adac11010c6caceca2cc43cc139c7330ea b/Packages/NB_FX/.git.backup/objects/f6/7a36adac11010c6caceca2cc43cc139c7330ea new file mode 100644 index 00000000..3d40328e Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f6/7a36adac11010c6caceca2cc43cc139c7330ea differ diff --git a/Packages/NB_FX/.git.backup/objects/f6/7e45866bc5a17d71b83e83a9426e1bc3a453e8 b/Packages/NB_FX/.git.backup/objects/f6/7e45866bc5a17d71b83e83a9426e1bc3a453e8 new file mode 100644 index 00000000..151e508b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f6/7e45866bc5a17d71b83e83a9426e1bc3a453e8 differ diff --git a/Packages/NB_FX/.git.backup/objects/f7/23a9c02fcba6e4a427b1b0a7e39821ca25ff2b b/Packages/NB_FX/.git.backup/objects/f7/23a9c02fcba6e4a427b1b0a7e39821ca25ff2b new file mode 100644 index 00000000..df190b55 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f7/23a9c02fcba6e4a427b1b0a7e39821ca25ff2b differ diff --git a/Packages/NB_FX/.git.backup/objects/f7/a424063e2c4cb956874bacfea79835c950206b b/Packages/NB_FX/.git.backup/objects/f7/a424063e2c4cb956874bacfea79835c950206b new file mode 100644 index 00000000..2eb80ffe Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f7/a424063e2c4cb956874bacfea79835c950206b differ diff --git a/Packages/NB_FX/.git.backup/objects/f7/c5f32015d38411010fcdf9253de54e58c037bb b/Packages/NB_FX/.git.backup/objects/f7/c5f32015d38411010fcdf9253de54e58c037bb new file mode 100644 index 00000000..240e4e0b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f7/c5f32015d38411010fcdf9253de54e58c037bb differ diff --git a/Packages/NB_FX/.git.backup/objects/f7/d3e0f429d2d76364d826639f8d23396fdd086a b/Packages/NB_FX/.git.backup/objects/f7/d3e0f429d2d76364d826639f8d23396fdd086a new file mode 100644 index 00000000..c6a2fa9d Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f7/d3e0f429d2d76364d826639f8d23396fdd086a differ diff --git a/Packages/NB_FX/.git.backup/objects/f7/e663c7551a0b244721cf4a4fbb04f266acf029 b/Packages/NB_FX/.git.backup/objects/f7/e663c7551a0b244721cf4a4fbb04f266acf029 new file mode 100644 index 00000000..18d3ea0f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f7/e663c7551a0b244721cf4a4fbb04f266acf029 differ diff --git a/Packages/NB_FX/.git.backup/objects/f8/536a4468d39fb055939ff7f21bc59aebbfa962 b/Packages/NB_FX/.git.backup/objects/f8/536a4468d39fb055939ff7f21bc59aebbfa962 new file mode 100644 index 00000000..a47d4f8f Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f8/536a4468d39fb055939ff7f21bc59aebbfa962 differ diff --git a/Packages/NB_FX/.git.backup/objects/f8/7de960b06cf7bd0a7e465ac36cded59366a9d5 b/Packages/NB_FX/.git.backup/objects/f8/7de960b06cf7bd0a7e465ac36cded59366a9d5 new file mode 100644 index 00000000..23c9b21b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f8/7de960b06cf7bd0a7e465ac36cded59366a9d5 differ diff --git a/Packages/NB_FX/.git.backup/objects/f8/c4ff5976bc4999b9c3107ea8c0bc3e30f97fc0 b/Packages/NB_FX/.git.backup/objects/f8/c4ff5976bc4999b9c3107ea8c0bc3e30f97fc0 new file mode 100644 index 00000000..f3b18ca6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f8/c4ff5976bc4999b9c3107ea8c0bc3e30f97fc0 differ diff --git a/Packages/NB_FX/.git.backup/objects/f8/f639796571ee4bc63ee99ddc6ff7ea11ae054d b/Packages/NB_FX/.git.backup/objects/f8/f639796571ee4bc63ee99ddc6ff7ea11ae054d new file mode 100644 index 00000000..a2fef5fd Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f8/f639796571ee4bc63ee99ddc6ff7ea11ae054d differ diff --git a/Packages/NB_FX/.git.backup/objects/f8/fedc677c7b9f36aa7f09b31533defe19c6221e b/Packages/NB_FX/.git.backup/objects/f8/fedc677c7b9f36aa7f09b31533defe19c6221e new file mode 100644 index 00000000..5cbc3fec Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f8/fedc677c7b9f36aa7f09b31533defe19c6221e differ diff --git a/Packages/NB_FX/.git.backup/objects/f9/5e78ecfec5c6f0af2be514ad95fd779eaf6d84 b/Packages/NB_FX/.git.backup/objects/f9/5e78ecfec5c6f0af2be514ad95fd779eaf6d84 new file mode 100644 index 00000000..913ccb92 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f9/5e78ecfec5c6f0af2be514ad95fd779eaf6d84 differ diff --git a/Packages/NB_FX/.git.backup/objects/f9/5fb07bf4f7369984187fe2c95c16bf875fcfad b/Packages/NB_FX/.git.backup/objects/f9/5fb07bf4f7369984187fe2c95c16bf875fcfad new file mode 100644 index 00000000..5a3643d8 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f9/5fb07bf4f7369984187fe2c95c16bf875fcfad differ diff --git a/Packages/NB_FX/.git.backup/objects/f9/691aee2964a5d7b07288efc5c2df266b2d58ce b/Packages/NB_FX/.git.backup/objects/f9/691aee2964a5d7b07288efc5c2df266b2d58ce new file mode 100644 index 00000000..4d4ea12b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f9/691aee2964a5d7b07288efc5c2df266b2d58ce differ diff --git a/Packages/NB_FX/.git.backup/objects/f9/75cafd68dd553797f9d90316ca19e4ed7faee6 b/Packages/NB_FX/.git.backup/objects/f9/75cafd68dd553797f9d90316ca19e4ed7faee6 new file mode 100644 index 00000000..2c776fed Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f9/75cafd68dd553797f9d90316ca19e4ed7faee6 differ diff --git a/Packages/NB_FX/.git.backup/objects/f9/d2a68415d86361b4a3f24e07ae835aca1808c3 b/Packages/NB_FX/.git.backup/objects/f9/d2a68415d86361b4a3f24e07ae835aca1808c3 new file mode 100644 index 00000000..efa6e638 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f9/d2a68415d86361b4a3f24e07ae835aca1808c3 differ diff --git a/Packages/NB_FX/.git.backup/objects/f9/ef0c0ec1f50b9a8b200c258799d231b8475174 b/Packages/NB_FX/.git.backup/objects/f9/ef0c0ec1f50b9a8b200c258799d231b8475174 new file mode 100644 index 00000000..cd7db9ef Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f9/ef0c0ec1f50b9a8b200c258799d231b8475174 differ diff --git a/Packages/NB_FX/.git.backup/objects/f9/f2343b0ccbc2d8f5c2bbc29d883025860ea98b b/Packages/NB_FX/.git.backup/objects/f9/f2343b0ccbc2d8f5c2bbc29d883025860ea98b new file mode 100644 index 00000000..cdbc12ab Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/f9/f2343b0ccbc2d8f5c2bbc29d883025860ea98b differ diff --git a/Packages/NB_FX/.git.backup/objects/fa/2d82e15f3a623ef694096ebba98b9c31960837 b/Packages/NB_FX/.git.backup/objects/fa/2d82e15f3a623ef694096ebba98b9c31960837 new file mode 100644 index 00000000..fcda9c01 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fa/2d82e15f3a623ef694096ebba98b9c31960837 differ diff --git a/Packages/NB_FX/.git.backup/objects/fb/5d9cee8f57ca80fd8a3417ba3b0099a8a29018 b/Packages/NB_FX/.git.backup/objects/fb/5d9cee8f57ca80fd8a3417ba3b0099a8a29018 new file mode 100644 index 00000000..96be8fd3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fb/5d9cee8f57ca80fd8a3417ba3b0099a8a29018 differ diff --git a/Packages/NB_FX/.git.backup/objects/fb/7c62b842cf932b34205212882167be0229ae39 b/Packages/NB_FX/.git.backup/objects/fb/7c62b842cf932b34205212882167be0229ae39 new file mode 100644 index 00000000..df61e8bd Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fb/7c62b842cf932b34205212882167be0229ae39 differ diff --git a/Packages/NB_FX/.git.backup/objects/fb/e599b7f706deef952e8c02f51b99000c9a8165 b/Packages/NB_FX/.git.backup/objects/fb/e599b7f706deef952e8c02f51b99000c9a8165 new file mode 100644 index 00000000..1729108c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fb/e599b7f706deef952e8c02f51b99000c9a8165 differ diff --git a/Packages/NB_FX/.git.backup/objects/fc/004debe66c50dabd78dba83e632e33d6612432 b/Packages/NB_FX/.git.backup/objects/fc/004debe66c50dabd78dba83e632e33d6612432 new file mode 100644 index 00000000..8d1cd700 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fc/004debe66c50dabd78dba83e632e33d6612432 differ diff --git a/Packages/NB_FX/.git.backup/objects/fc/514dfc793c63282fe5d77f44b7e0b194604a9e b/Packages/NB_FX/.git.backup/objects/fc/514dfc793c63282fe5d77f44b7e0b194604a9e new file mode 100644 index 00000000..71fdc722 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fc/514dfc793c63282fe5d77f44b7e0b194604a9e differ diff --git a/Packages/NB_FX/.git.backup/objects/fc/ee84935cd175f310743d6c3f7e897e72e936df b/Packages/NB_FX/.git.backup/objects/fc/ee84935cd175f310743d6c3f7e897e72e936df new file mode 100644 index 00000000..45bdb6f6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fc/ee84935cd175f310743d6c3f7e897e72e936df differ diff --git a/Packages/NB_FX/.git.backup/objects/fc/fd80fb728cfc11e78334ce5ad81d6e2502eb0b b/Packages/NB_FX/.git.backup/objects/fc/fd80fb728cfc11e78334ce5ad81d6e2502eb0b new file mode 100644 index 00000000..344b843c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fc/fd80fb728cfc11e78334ce5ad81d6e2502eb0b differ diff --git a/Packages/NB_FX/.git.backup/objects/fd/480a19ba10abb7a2ad37aa954905322b1604c8 b/Packages/NB_FX/.git.backup/objects/fd/480a19ba10abb7a2ad37aa954905322b1604c8 new file mode 100644 index 00000000..3dbc82f6 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fd/480a19ba10abb7a2ad37aa954905322b1604c8 differ diff --git a/Packages/NB_FX/.git.backup/objects/fe/a2829dcaabacb04f817d4d25636e8e6b08017a b/Packages/NB_FX/.git.backup/objects/fe/a2829dcaabacb04f817d4d25636e8e6b08017a new file mode 100644 index 00000000..a88090e1 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/fe/a2829dcaabacb04f817d4d25636e8e6b08017a differ diff --git a/Packages/NB_FX/.git.backup/objects/ff/0343baa0c7ec703cb86f596b722e5c1860a780 b/Packages/NB_FX/.git.backup/objects/ff/0343baa0c7ec703cb86f596b722e5c1860a780 new file mode 100644 index 00000000..13a9ef76 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ff/0343baa0c7ec703cb86f596b722e5c1860a780 differ diff --git a/Packages/NB_FX/.git.backup/objects/ff/06a9fb9656084a17a862ad6dde3f1cff7ba37f b/Packages/NB_FX/.git.backup/objects/ff/06a9fb9656084a17a862ad6dde3f1cff7ba37f new file mode 100644 index 00000000..2e52f713 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ff/06a9fb9656084a17a862ad6dde3f1cff7ba37f differ diff --git a/Packages/NB_FX/.git.backup/objects/ff/1ceb747341973b431e127c32c4c473796eb25c b/Packages/NB_FX/.git.backup/objects/ff/1ceb747341973b431e127c32c4c473796eb25c new file mode 100644 index 00000000..b60412d7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ff/1ceb747341973b431e127c32c4c473796eb25c differ diff --git a/Packages/NB_FX/.git.backup/objects/ff/8bcf5ad0372e0b731999984388ff3bdec5d1cc b/Packages/NB_FX/.git.backup/objects/ff/8bcf5ad0372e0b731999984388ff3bdec5d1cc new file mode 100644 index 00000000..ba8f86fa Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ff/8bcf5ad0372e0b731999984388ff3bdec5d1cc differ diff --git a/Packages/NB_FX/.git.backup/objects/ff/a0c325d423b8d448d4ac1ff44d5378cffa01c4 b/Packages/NB_FX/.git.backup/objects/ff/a0c325d423b8d448d4ac1ff44d5378cffa01c4 new file mode 100644 index 00000000..9f11e44b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ff/a0c325d423b8d448d4ac1ff44d5378cffa01c4 differ diff --git a/Packages/NB_FX/.git.backup/objects/ff/a4bc670e020fabfa87fdef53bce3f5fda1ed01 b/Packages/NB_FX/.git.backup/objects/ff/a4bc670e020fabfa87fdef53bce3f5fda1ed01 new file mode 100644 index 00000000..09bac60b Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ff/a4bc670e020fabfa87fdef53bce3f5fda1ed01 differ diff --git a/Packages/NB_FX/.git.backup/objects/ff/aeeccb3f74763df9997b8d0a7deea6d497731b b/Packages/NB_FX/.git.backup/objects/ff/aeeccb3f74763df9997b8d0a7deea6d497731b new file mode 100644 index 00000000..cef536b7 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/ff/aeeccb3f74763df9997b8d0a7deea6d497731b differ diff --git a/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.idx b/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.idx new file mode 100644 index 00000000..4456e7fc Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.idx differ diff --git a/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.pack b/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.pack new file mode 100644 index 00000000..dca08f77 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.pack differ diff --git a/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.rev b/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.rev new file mode 100644 index 00000000..279af249 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/pack/pack-0579d4e69b1ae7eb3dab6359943e4dbaa5bf18f0.rev differ diff --git a/Packages/NB_FX/.git.backup/objects/pack/pack-bf4325bb55f61f4b3c444257022436798820dcfd.idx b/Packages/NB_FX/.git.backup/objects/pack/pack-bf4325bb55f61f4b3c444257022436798820dcfd.idx new file mode 100644 index 00000000..ad444348 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/pack/pack-bf4325bb55f61f4b3c444257022436798820dcfd.idx differ diff --git a/Packages/NB_FX/.git.backup/objects/pack/pack-bf4325bb55f61f4b3c444257022436798820dcfd.pack b/Packages/NB_FX/.git.backup/objects/pack/pack-bf4325bb55f61f4b3c444257022436798820dcfd.pack new file mode 100644 index 00000000..796bde0c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/pack/pack-bf4325bb55f61f4b3c444257022436798820dcfd.pack differ diff --git a/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.idx b/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.idx new file mode 100644 index 00000000..0218be42 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.idx differ diff --git a/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.pack b/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.pack new file mode 100644 index 00000000..b3cbf69c Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.pack differ diff --git a/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.rev b/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.rev new file mode 100644 index 00000000..f43fdac0 Binary files /dev/null and b/Packages/NB_FX/.git.backup/objects/pack/pack-e1f29b1a532e7c57b353210d28d50f33520d7714.rev differ diff --git a/Packages/NB_FX/.git.backup/packed-refs b/Packages/NB_FX/.git.backup/packed-refs new file mode 100644 index 00000000..c687f8ba --- /dev/null +++ b/Packages/NB_FX/.git.backup/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +5e51bae4d646d321b278836a150240cd65c3e170 refs/remotes/origin/master diff --git a/Packages/NB_FX/.git.backup/refs/heads/feature/nbshader-2 b/Packages/NB_FX/.git.backup/refs/heads/feature/nbshader-2 new file mode 100644 index 00000000..f7f4b5fe --- /dev/null +++ b/Packages/NB_FX/.git.backup/refs/heads/feature/nbshader-2 @@ -0,0 +1 @@ +c99774e37f3796362ab73a04621ca058fab49b3a diff --git a/Packages/NB_FX/.git.backup/refs/heads/master b/Packages/NB_FX/.git.backup/refs/heads/master new file mode 100644 index 00000000..31fbdcd6 --- /dev/null +++ b/Packages/NB_FX/.git.backup/refs/heads/master @@ -0,0 +1 @@ +ee26c55dc0b55a14d06d3840a49da6c829246082 diff --git a/Packages/NB_FX/.git.backup/refs/remotes/origin/Dev/HDRP b/Packages/NB_FX/.git.backup/refs/remotes/origin/Dev/HDRP new file mode 100644 index 00000000..51587d07 --- /dev/null +++ b/Packages/NB_FX/.git.backup/refs/remotes/origin/Dev/HDRP @@ -0,0 +1 @@ +fa41b19c57420d8a51db2afeb96c3cc34ee6c440 diff --git a/Packages/NB_FX/.git.backup/refs/remotes/origin/HEAD b/Packages/NB_FX/.git.backup/refs/remotes/origin/HEAD new file mode 100644 index 00000000..6efe28ff --- /dev/null +++ b/Packages/NB_FX/.git.backup/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/Packages/NB_FX/.git.backup/refs/remotes/origin/feature/nbshader-2 b/Packages/NB_FX/.git.backup/refs/remotes/origin/feature/nbshader-2 new file mode 100644 index 00000000..f7f4b5fe --- /dev/null +++ b/Packages/NB_FX/.git.backup/refs/remotes/origin/feature/nbshader-2 @@ -0,0 +1 @@ +c99774e37f3796362ab73a04621ca058fab49b3a diff --git a/Packages/NB_FX/.git.backup/refs/remotes/origin/feature/vat b/Packages/NB_FX/.git.backup/refs/remotes/origin/feature/vat new file mode 100644 index 00000000..3d04388c --- /dev/null +++ b/Packages/NB_FX/.git.backup/refs/remotes/origin/feature/vat @@ -0,0 +1 @@ +038d9f01f9ca65ec35655c8d75dabc2a6dbc7586 diff --git a/Packages/NB_FX/.git.backup/refs/remotes/origin/master b/Packages/NB_FX/.git.backup/refs/remotes/origin/master new file mode 100644 index 00000000..31fbdcd6 --- /dev/null +++ b/Packages/NB_FX/.git.backup/refs/remotes/origin/master @@ -0,0 +1 @@ +ee26c55dc0b55a14d06d3840a49da6c829246082 diff --git a/Packages/NB_FX/.git.backup/tortoisegit.data b/Packages/NB_FX/.git.backup/tortoisegit.data new file mode 100644 index 00000000..fbe5fe18 Binary files /dev/null and b/Packages/NB_FX/.git.backup/tortoisegit.data differ diff --git a/Packages/NB_FX/.git.backup/tortoisegit.index b/Packages/NB_FX/.git.backup/tortoisegit.index new file mode 100644 index 00000000..dd110fb3 Binary files /dev/null and b/Packages/NB_FX/.git.backup/tortoisegit.index differ diff --git a/Packages/NB_FX/.gitattributes b/Packages/NB_FX/.gitattributes new file mode 100644 index 00000000..90a222de --- /dev/null +++ b/Packages/NB_FX/.gitattributes @@ -0,0 +1,18 @@ +*.ab filter=lfs diff=lfs merge=lfs -text +*.tga filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text +*.jpeg filter=lfs diff=lfs merge=lfs -text +*.bmp filter=lfs diff=lfs merge=lfs -text +*.gif filter=lfs diff=lfs merge=lfs -text +*.dds filter=lfs diff=lfs merge=lfs -text +*.webp filter=lfs diff=lfs merge=lfs -text +*.ktx filter=lfs diff=lfs merge=lfs -text +*.ktx2 filter=lfs diff=lfs merge=lfs -text +*.pvr filter=lfs diff=lfs merge=lfs -text +*.astc filter=lfs diff=lfs merge=lfs -text +*.exr filter=lfs diff=lfs merge=lfs -text +*.hdr filter=lfs diff=lfs merge=lfs -text +*.tif filter=lfs diff=lfs merge=lfs -text +*.tiff filter=lfs diff=lfs merge=lfs -text +*.psd filter=lfs diff=lfs merge=lfs -text diff --git a/Packages/NB_FX/.gitignore b/Packages/NB_FX/.gitignore new file mode 100644 index 00000000..4b579074 --- /dev/null +++ b/Packages/NB_FX/.gitignore @@ -0,0 +1,6 @@ +# macOS 自动生成的文件 +.DS_Store +**/.DS_Store +# macOS 自动生成的文件(下面两行会让所有 .DS_Store 被忽略) +.DS_Store +**/.DS_Store diff --git a/Packages/NB_FX/NBPostProcessing.meta b/Packages/NB_FX/NBPostProcessing.meta new file mode 100644 index 00000000..475a68d7 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3936a867430e83f4cbda293633399068 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/3DPostionShake.asset b/Packages/NB_FX/NBPostProcessing/3DPostionShake.asset new file mode 100644 index 00000000..ca980753 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/3DPostionShake.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6565214a344ac072734f1deda0a71b7cacf50d82c860c2f7a7c6896422f75908 +size 1961 diff --git a/Packages/NB_FX/NBPostProcessing/3DPostionShake.asset.meta b/Packages/NB_FX/NBPostProcessing/3DPostionShake.asset.meta new file mode 100644 index 00000000..02f2c88c --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/3DPostionShake.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3a1931bdb3088e4ebf4755df90c90e9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Editor.meta b/Packages/NB_FX/NBPostProcessing/Editor.meta new file mode 100644 index 00000000..7eb97032 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0b3052f0c1288a045a0be3d63f109623 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingControllerGUI.cs b/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingControllerGUI.cs new file mode 100644 index 00000000..5f8aeabe --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingControllerGUI.cs @@ -0,0 +1,340 @@ +using UnityEngine; +using UnityEditor; +using UnityEditor.AnimatedValues; +using System.Reflection; +#if CINIMACHINE_3_0 +using Unity.Cinemachine; +#endif +using NBShader; + +using System; +// using Unity.Properties; +namespace NBShaderEditor +{ + + [CustomEditor(typeof(PostProcessingController))] + public class PostProcessingControllerGUI : Editor + { + private SerializedProperty _managerProperty; + private SerializedProperty _indexProperty; + + private Action delayExcuteReflect = () => { }; + + public override void OnInspectorGUI() + { + PostProcessingController ppController = (PostProcessingController)target; + serializedObject.Update(); + + _managerProperty = serializedObject.FindProperty("_manager"); + _indexProperty = serializedObject.FindProperty("_index"); + EditorGUI.BeginDisabledGroup(true); + EditorGUILayout.PropertyField(_managerProperty); + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginChangeCheck(); + SerializedProperty customScreenCenterPosProp = serializedObject.FindProperty("customScreenCenterPos"); + EditorGUILayout.PropertyField(customScreenCenterPosProp, new GUIContent("自定义屏幕中心")); + + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("SetScreenCenterPos", ppController); + } + + SerializedProperty caToggleProp = serializedObject.FindProperty("chromaticAberrationToggle"); + DrawToggleFoldOut(ppController.AnimBools[0], "色散", caToggleProp, + drawEndChangeCheck: isChangeToggle => { ReflectMethod("InitAllSettings", ppController); } + , drawBlock: isToggle => + { + EditorGUI.BeginChangeCheck(); + SerializedProperty caFromDistortProp = serializedObject.FindProperty("caFromDistort"); + EditorGUILayout.PropertyField(caFromDistortProp, new GUIContent("色散UV跟随后处理扭曲")); + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("SetUVFromDistort", ppController); + } + + SerializedProperty caIntensityProps = serializedObject.FindProperty("chromaticAberrationIntensity"); + EditorGUILayout.PropertyField(caIntensityProps, new GUIContent("色散强度")); + + if (!ppController.caFromDistort) + { + SerializedProperty caPosProp = serializedObject.FindProperty("chromaticAberrationPos"); + EditorGUILayout.PropertyField(caPosProp, new GUIContent("色散位置")); + + SerializedProperty caRangeProp = serializedObject.FindProperty("chromaticAberrationRange"); + EditorGUILayout.PropertyField(caRangeProp, new GUIContent("色散过渡范围")); + } + }); + + SerializedProperty distortSpeedToggleProp = serializedObject.FindProperty("distortSpeedToggle"); + DrawToggleFoldOut(ppController.AnimBools[1], "扭曲", distortSpeedToggleProp, drawEndChangeCheck: + isChangeToggle => { ReflectMethod("InitAllSettings", ppController); }, + drawBlock: isToggle => + { + EditorGUI.BeginChangeCheck(); + SerializedProperty distortScreenUVModeProp = serializedObject.FindProperty("distortScreenUVMode"); + EditorGUILayout.PropertyField(distortScreenUVModeProp, new GUIContent("后处理走常规屏幕坐标")); + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("SetUVFromDistort", ppController); + } + + EditorGUI.BeginChangeCheck(); + SerializedProperty distortSpeedTextureProp = serializedObject.FindProperty("distortSpeedTexture"); + EditorGUILayout.PropertyField(distortSpeedTextureProp, new GUIContent("后处理扭曲贴图")); + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("InitAllSettings", ppController); + } + + if (ppController.distortScreenUVMode) + { + EditorGUI.BeginChangeCheck(); + SerializedProperty distortTextureMidValueProp = + serializedObject.FindProperty("distortTextureMidValue"); + EditorGUILayout.PropertyField(distortTextureMidValueProp, new GUIContent("扭曲贴图中间值")); + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("SetTexture", ppController); + } + } + + + SerializedProperty distortSpeedTexStProp = serializedObject.FindProperty("distortSpeedTexSt"); + EditorGUILayout.PropertyField(distortSpeedTexStProp, new GUIContent("扭曲贴图缩放平移")); + SerializedProperty distortSpeedIntensityProp = + serializedObject.FindProperty("distortSpeedIntensity"); + EditorGUILayout.PropertyField(distortSpeedIntensityProp, new GUIContent("扭曲强度")); + + if (!ppController.distortScreenUVMode) + { + SerializedProperty distortSpeedPositionProp = + serializedObject.FindProperty("distortSpeedPosition"); + EditorGUILayout.PropertyField(distortSpeedPositionProp, new GUIContent("扭曲位置")); + SerializedProperty distortSpeedRangeProp = serializedObject.FindProperty("distortSpeedRange"); + EditorGUILayout.PropertyField(distortSpeedRangeProp, new GUIContent("扭曲过渡范围")); + } + + SerializedProperty distortSpeedMoveSpeedXProp = + serializedObject.FindProperty("distortSpeedMoveSpeedX"); + EditorGUILayout.PropertyField(distortSpeedMoveSpeedXProp, new GUIContent("扭曲纹理流动X")); + SerializedProperty distortSpeedMoveSpeed = serializedObject.FindProperty("distortSpeedMoveSpeed"); + EditorGUILayout.PropertyField(distortSpeedMoveSpeed, new GUIContent("扭曲纹理流动Y")); + }); + + + SerializedProperty radialBlurToggleProp = serializedObject.FindProperty("radialBlurToggle"); + DrawToggleFoldOut(ppController.AnimBools[2], "径向模糊", radialBlurToggleProp, drawEndChangeCheck: + isChangeToggle => { ReflectMethod("InitAllSettings", ppController); }, + drawBlock: isToggle => + { + EditorGUI.BeginChangeCheck(); + SerializedProperty radialBlurFromDistortProp = + serializedObject.FindProperty("radialBlurFromDistort"); + EditorGUILayout.PropertyField(radialBlurFromDistortProp, new GUIContent("径向模糊跟随后处理扭曲")); + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("SetUVFromDistort", ppController); + } + + SerializedProperty radialBlurSampleCountProp = + serializedObject.FindProperty("radialBlurSampleCount"); + EditorGUILayout.PropertyField(radialBlurSampleCountProp, new GUIContent("采样次数")); + SerializedProperty radialBlurIntensityProp = serializedObject.FindProperty("radialBlurIntensity"); + EditorGUILayout.PropertyField(radialBlurIntensityProp, new GUIContent("强度")); + if (!ppController.radialBlurFromDistort) + { + SerializedProperty radialBlurPosProp = serializedObject.FindProperty("radialBlurPos"); + EditorGUILayout.PropertyField(radialBlurPosProp, new GUIContent("位置")); + SerializedProperty radialBlurRangeProp = serializedObject.FindProperty("radialBlurRange"); + EditorGUILayout.PropertyField(radialBlurRangeProp, new GUIContent("过渡范围")); + } + }); + +#if CINIMACHINE_3_0 + SerializedProperty cameraShakeToggleProp = serializedObject.FindProperty("cameraShakeToggle"); + DrawToggleFoldOut(ppController.AnimBools[3], "震屏", cameraShakeToggleProp, drawEndChangeCheck: + isChangeToggle => { ReflectMethod("InitAllSettings", ppController); }, + drawBlock: isToggle => + { + + EditorGUI.BeginChangeCheck(); + SerializedProperty cinemachineCameraProp = serializedObject.FindProperty("cinemachineCamera"); + EditorGUILayout.PropertyField(cinemachineCameraProp, new GUIContent("绑定Cinemachine相机")); + if (EditorGUI.EndChangeCheck()) + { + ppController.InitCinemachineCamera(); + } + + SerializedProperty cameraShakeIntensityProp = serializedObject.FindProperty("cameraShakeIntensity"); + EditorGUILayout.PropertyField(cameraShakeIntensityProp, new GUIContent("相机震动强度")); + }); +#endif + + SerializedProperty overlayTextureToggleProp = serializedObject.FindProperty("overlayTextureToggle"); + DrawToggleFoldOut(ppController.AnimBools[4], "肌理叠加图", overlayTextureToggleProp, + drawEndChangeCheck: isChangeToggle => { ReflectMethod("InitAllSettings", ppController); }, + drawBlock: isToggle => + { + EditorGUI.BeginChangeCheck(); + SerializedProperty overlayTexturePolarCoordModeProp = + serializedObject.FindProperty("overlayTexturePolarCoordMode"); + EditorGUILayout.PropertyField(overlayTexturePolarCoordModeProp, new GUIContent("肌理图极坐标模式")); + SerializedProperty overlayTextureProp = serializedObject.FindProperty("overlayTexture"); + EditorGUILayout.PropertyField(overlayTextureProp, new GUIContent("肌理图")); + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("SetTexture", ppController); + } + + SerializedProperty overlayTextureStProp = serializedObject.FindProperty("overlayTextureSt"); + EditorGUILayout.PropertyField(overlayTextureStProp, new GUIContent("肌理图缩放平移")); + SerializedProperty overlayTextureAnimProp = serializedObject.FindProperty("overlayTextureAnim"); + EditorGUILayout.PropertyField(overlayTextureAnimProp, new GUIContent("肌理图偏移动画")); + SerializedProperty overlayTextureIntensityProp = + serializedObject.FindProperty("overlayTextureIntensity"); + EditorGUILayout.PropertyField(overlayTextureIntensityProp, new GUIContent("肌理图强度")); + + EditorGUI.BeginChangeCheck(); + SerializedProperty overlayMaskTextureProp = serializedObject.FindProperty("overlayMaskTexture"); + EditorGUILayout.PropertyField(overlayMaskTextureProp, new GUIContent("肌理蒙版图")); + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("SetTexture", ppController); + } + + SerializedProperty overlayMaskTextureStProp = serializedObject.FindProperty("overlayMaskTextureSt"); + EditorGUILayout.PropertyField(overlayMaskTextureStProp, new GUIContent("肌理图蒙版缩放平移")); + + }); + + SerializedProperty flashToggleProp = serializedObject.FindProperty("flashToggle"); + DrawToggleFoldOut(ppController.AnimBools[5], "反闪", flashToggleProp, drawEndChangeCheck: + isChangeToggle => { ReflectMethod("InitAllSettings", ppController); }, + drawBlock: isToggle => + { + SerializedProperty flashIntensityProp = serializedObject.FindProperty("flashIntensity"); + EditorGUILayout.PropertyField(flashIntensityProp, new GUIContent("反转效果强度")); + SerializedProperty flashGradientRangeProp = serializedObject.FindProperty("flashGradientRange"); + EditorGUILayout.PropertyField(flashGradientRangeProp, new GUIContent("过渡起始亮度")); + SerializedProperty flashContrastProp = serializedObject.FindProperty("flashContrast"); + EditorGUILayout.PropertyField(flashContrastProp, new GUIContent("过渡范围")); + SerializedProperty flashColorProp = serializedObject.FindProperty("flashColor"); + EditorGUILayout.PropertyField(flashColorProp, new GUIContent("亮部闪颜色")); + SerializedProperty blackFlashColorProp = serializedObject.FindProperty("blackFlashColor"); + EditorGUILayout.PropertyField(blackFlashColorProp, new GUIContent("暗部闪颜色")); + SerializedProperty flashInvertIntensityProp = serializedObject.FindProperty("flashInvertIntensity"); + EditorGUILayout.PropertyField(flashInvertIntensityProp, new GUIContent("反转度")); + + EditorGUI.BeginChangeCheck(); + SerializedProperty flashTexture = serializedObject.FindProperty("flashTexture"); + EditorGUILayout.PropertyField(flashTexture, new GUIContent("反闪纹理图")); + SerializedProperty flashTexturePolarCoordModeProp = serializedObject.FindProperty("flashTexturePolarCoordMode"); + EditorGUILayout.PropertyField(flashTexturePolarCoordModeProp, new GUIContent("反闪纹理图极坐标模式")); + if (EditorGUI.EndChangeCheck()) + { + ReflectMethod("SetTexture", ppController); + } + SerializedProperty flashTextureScaleOffsetProp = serializedObject.FindProperty("flashTextureScaleOffset"); + EditorGUILayout.PropertyField(flashTextureScaleOffsetProp, new GUIContent("反闪纹理图缩放平移")); + SerializedProperty flashVecProp = serializedObject.FindProperty("flashVec"); + EditorGUILayout.PropertyField(flashVecProp, new GUIContent("反闪纹理图偏移速度")); + SerializedProperty flashDeSaturateIntensityProp = serializedObject.FindProperty("flashDeSaturateIntensity"); + EditorGUILayout.PropertyField(flashDeSaturateIntensityProp, new GUIContent("纹理图Pow")); + SerializedProperty flashTextureIntensityProp = serializedObject.FindProperty("flashTextureIntensity"); + EditorGUILayout.PropertyField(flashTextureIntensityProp, new GUIContent("纹理图混合程度")); + SerializedProperty flashVecZWProp = serializedObject.FindProperty("flashVecZW"); + EditorGUILayout.PropertyField(flashVecZWProp, new GUIContent("反闪纹理图遮罩位置/过渡范围")); + + }); + + SerializedProperty vignetteToggleProp = serializedObject.FindProperty("vignetteToggle"); + DrawToggleFoldOut(ppController.AnimBools[6], "暗角", vignetteToggleProp, drawEndChangeCheck: + isChangeToggle => { ReflectMethod("InitAllSettings", ppController); }, + drawBlock: isToggle => + { + SerializedProperty vignetteColorProp = serializedObject.FindProperty("vignetteColor"); + EditorGUILayout.PropertyField(vignetteColorProp, new GUIContent("暗角颜色")); + SerializedProperty vignetteIntensityProp = serializedObject.FindProperty("vignetteIntensity"); + EditorGUILayout.PropertyField(vignetteIntensityProp, new GUIContent("暗角强度")); + SerializedProperty vignetteRoundnessProp = serializedObject.FindProperty("vignetteRoundness"); + EditorGUILayout.PropertyField(vignetteRoundnessProp, new GUIContent("暗角圆度")); + SerializedProperty vignetteSmothnessProp = serializedObject.FindProperty("vignetteSmothness"); + EditorGUILayout.PropertyField(vignetteSmothnessProp, new GUIContent("暗角平滑度")); + SerializedProperty vignetteFillProp = serializedObject.FindProperty("vignetteFill"); + EditorGUILayout.PropertyField(vignetteFillProp, new GUIContent("暗角填充度")); + }); + + if (GUILayout.Button("选择当前Manager")) + { + ReflectMethod("FindManager", ppController); + } +#if CINIMACHINE_3_0 + if (GUILayout.Button("选择当前CinemachineCamera")) + { + ppController.FindVirtualCamera(); + } +#endif + + serializedObject.ApplyModifiedProperties(); + + } + + public void DrawToggleFoldOut(AnimBool foldOutAnimBool, string label, SerializedProperty boolProperty, + bool isIndentBlock = true, + FontStyle fontStyle = FontStyle.Bold, + Action drawBlock = null, Action drawEndChangeCheck = null) + { + if (fontStyle == FontStyle.Bold) + { + EditorGUILayout.Space(); + } + + EditorGUILayout.BeginHorizontal(); + var rect = EditorGUILayout.GetControlRect(); + + var foldoutRect = new Rect(rect.x, rect.y, rect.width, rect.height); + var labelRect = new Rect(rect.x + 18f, rect.y, rect.width - 18f, rect.height); + + EditorGUI.BeginChangeCheck(); + EditorGUI.PropertyField(rect, boolProperty, new GUIContent("")); + if (EditorGUI.EndChangeCheck()) + { + drawEndChangeCheck?.Invoke(boolProperty.boolValue); + } + + foldOutAnimBool.target = EditorGUI.Foldout(foldoutRect, foldOutAnimBool.target, string.Empty, true); + var origFontStyle = EditorStyles.label.fontStyle; + EditorStyles.label.fontStyle = fontStyle; + EditorGUI.LabelField(labelRect, label); + EditorStyles.label.fontStyle = origFontStyle; + EditorGUILayout.EndHorizontal(); + if (isIndentBlock) EditorGUI.indentLevel++; + float faded = foldOutAnimBool.faded; + if (faded == 0) faded = 0.00001f; //用于欺骗FadeGroup,不要让他真的关闭了。这样会藏不住相关的GUI。我们的目的是,GUI藏住,但是逻辑还是在跑。drawBlock要执行。 + EditorGUILayout.BeginFadeGroup(faded); + { + EditorGUI.BeginDisabledGroup(!boolProperty.boolValue); + drawBlock?.Invoke(boolProperty.boolValue); + EditorGUI.EndDisabledGroup(); + } + EditorGUILayout.EndFadeGroup(); + if (isIndentBlock) EditorGUI.indentLevel--; + } + + void ReflectMethod(string methodName, PostProcessingController controller) + { + serializedObject.ApplyModifiedProperties(); + MethodInfo privateMethod = + typeof(PostProcessingController).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + if (privateMethod != null) + { + privateMethod.Invoke(controller, null); + } + else + { + Debug.LogError("Private method " + methodName + " not found!"); + } + } + } +} \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingControllerGUI.cs.meta b/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingControllerGUI.cs.meta new file mode 100644 index 00000000..56b0cc48 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingControllerGUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed187d8c0d9f5b14aa156ff45e7405c7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingManagerGUI.cs b/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingManagerGUI.cs new file mode 100644 index 00000000..2546f6a5 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingManagerGUI.cs @@ -0,0 +1,75 @@ +using UnityEngine; +using UnityEditor; +using System.Reflection; +using NBShader; + +namespace NBShaderEditor +{ + [CustomEditor(typeof(PostProcessingManager))] + public class PostProcessingManagerGUI : Editor + { + private PostProcessingManager _ppManager; + public override void OnInspectorGUI() + { + + _ppManager = (PostProcessingManager)target; + serializedObject.Update(); + DrawToggle("controllerIndexFlags","_controllerIndexFlags"); + DrawToggle("色散开关",PostProcessingManager.chromaticAberrationToggles); + DrawToggle("径向扭曲开关",PostProcessingManager.distortSpeedToggles); + DrawToggle("径向模糊开关",PostProcessingManager.radialBlurToggles); + #if CINIMACHINE_3_0 + DrawToggle("震屏开关",PostProcessingManager.cameraShakeToggles); + #endif + DrawToggle("肌理开关",PostProcessingManager.overlayTextureToggles); + DrawToggle("黑白闪开关",PostProcessingManager.flashToggles); + DrawToggle("暗角开关",PostProcessingManager.vignetteToggles); + if (PostProcessingManager.material) + { + DrawToggle32("ShaderFlags", PostProcessingManager.material.GetInteger(NBPostProcessFlags.FlagsId)); + } + + } + + void DrawToggle(string label, string propertyName) + { + int intValue = ReflectIntValue(propertyName); + DrawToggle(label,intValue); + } + + void DrawToggle(string label, int intValue) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(label); + EditorGUILayout.LabelField(BinaryIntDrawer.DrawBinaryInt(intValue,8)); + EditorGUILayout.EndHorizontal(); + } + void DrawToggle32(string label, int intValue) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(label); + EditorGUILayout.LabelField(BinaryIntDrawer.DrawBinaryInt(intValue,32)); + EditorGUILayout.EndHorizontal(); + } + + int ReflectIntValue(string propertyName) + { + + FieldInfo privateField = typeof(PostProcessingManager).GetField(propertyName, BindingFlags.NonPublic | BindingFlags.Instance); + + if (privateField != null) + { + // 获取私有字段的值 + int value = (int)privateField.GetValue(_ppManager); + return value; + } + else + { + Debug.LogError("PostProcessingManagerGUI获取变量错误"); + return -1; + } + + } + + } +} \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingManagerGUI.cs.meta b/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingManagerGUI.cs.meta new file mode 100644 index 00000000..db7943c3 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Editor/PostProcessingManagerGUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7bf2aa095c38c4972ba5c008ae40a3f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Editor/com.xuanxuan.nb.postprocessing.Editor.asmdef b/Packages/NB_FX/NBPostProcessing/Editor/com.xuanxuan.nb.postprocessing.Editor.asmdef new file mode 100644 index 00000000..99f989ff --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Editor/com.xuanxuan.nb.postprocessing.Editor.asmdef @@ -0,0 +1,27 @@ +{ + "name": "com.xuanxuan.nb.postprocessing.Editor", + "rootNamespace": "", + "references": [ + "GUID:a1f23b61b189bd949adfd0f7a353734f", + "GUID:8495541fcd41b0c40b5b6e6e7a7639d1", + "GUID:8f9e4d586616f13449cfeb86c5f704c2", + "GUID:4307f53044263cf4b835bd812fc161a4" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.cinemachine", + "expression": "3.0", + "define": "CINIMACHINE_3_0" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Editor/com.xuanxuan.nb.postprocessing.Editor.asmdef.meta b/Packages/NB_FX/NBPostProcessing/Editor/com.xuanxuan.nb.postprocessing.Editor.asmdef.meta new file mode 100644 index 00000000..203bf75e --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Editor/com.xuanxuan.nb.postprocessing.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 12fb0c569d0951c40a3f4013cd8758b5 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Runtime.meta b/Packages/NB_FX/NBPostProcessing/Runtime.meta new file mode 100644 index 00000000..68ada299 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f0e3118134388949838b53cc48e9c89 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/DisturbanceMaskRenderPass.cs b/Packages/NB_FX/NBPostProcessing/Runtime/DisturbanceMaskRenderPass.cs new file mode 100644 index 00000000..e098ccda --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/DisturbanceMaskRenderPass.cs @@ -0,0 +1,387 @@ +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; +using System.Collections.Generic; +#if UNIVERSAL_RP_17_0_OR_NEWER +using UnityEngine.Experimental.Rendering; +using UnityEngine.Rendering.RenderGraphModule; +using UnityEngine.Rendering.RenderGraphModule.Util; +#endif + +namespace NBShader +{ + public class DisturbanceMaskRenderPass : ScriptableRenderPass + { + private ProfilingSampler _profilingSampler; + #if UNIVERSAL_RP_13_1_2_OR_NEWER + private RTHandle _DisturbanceMaskRTHandle; + private RTHandle _cameraDepthRTHandle; + private RTHandle _DownRT; + #else + private static readonly int _DisturbanceMaskRTID = Shader.PropertyToID("_DisturbanceMaskRT"); + private static readonly int _DownRTID = Shader.PropertyToID("_DisturbanceMaskTex"); + private RenderTargetIdentifier _DisturbanceMaskRTHandle = new RenderTargetIdentifier (_DisturbanceMaskRTID); + private RenderTargetIdentifier _cameraDepthRTHandle; + private RenderTargetIdentifier _DownRT = new RenderTargetIdentifier (_DownRTID); + #endif + private Material tempMat; + + private readonly Downsampling _downSampling; + + private Material _renderMaskMat ; + // public LayerMask _DisturbanceMaskLayer = 1 << 25; + private FilteringSettings _Filtering; + private static readonly int CameraTexture = Shader.PropertyToID("_CameraTexture"); + private static readonly int SampleOffset = Shader.PropertyToID("_SampleOffset"); + private static readonly int DisturbanceMaskTex = Shader.PropertyToID("_DisturbanceMaskTex"); + private readonly Color _clearDisturbanceMaskColor = new Color(0f, 0f, 0f, 1f); + + private readonly List _shaderTag = new List() + { + // new ShaderTagId("UniversalForward"), + // new ShaderTagId("SRPDefaultUnlit"), + // new ShaderTagId("UniversalForwardOnly") + new ShaderTagId("NBDeferredDistortPass") + }; + + public DisturbanceMaskRenderPass(ProfilingSampler profilingSampler,Material DisturbanceMaskMat, Downsampling downSampling) + { + _profilingSampler = profilingSampler; + _renderMaskMat = DisturbanceMaskMat; + _downSampling = downSampling; + } + +#if UNIVERSAL_RP_17_0_OR_NEWER + private class RenderGraphMaskPassData + { + public RendererListHandle rendererListHandle; + } + + private class GlobalTexturePassData + { + public TextureHandle texture; + public int nameID; + } + + private static bool IsSupportedCamera(CameraType cameraType) + { + return cameraType == CameraType.Game || cameraType == CameraType.SceneView; + } + + private static void SetGlobalTextureAfterPass(RenderGraph renderGraph, TextureHandle texture, int nameID, string passName) + { + using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData)) + { + passData.texture = texture; + passData.nameID = nameID; + builder.UseTexture(texture, AccessFlags.Read); + builder.AllowPassCulling(false); + builder.AllowGlobalStateModification(true); + builder.SetGlobalTextureAfterPass(texture, nameID); + builder.SetRenderFunc(static (GlobalTexturePassData data, RasterGraphContext context) => + { + }); + } + } + + private void ApplyDownsampling(ref TextureDesc descriptor) + { + switch (_downSampling) + { + case Downsampling._2xBilinear: + descriptor.width = Mathf.Max(1, descriptor.width / 2); + descriptor.height = Mathf.Max(1, descriptor.height / 2); + break; + case Downsampling._4xBilinear: + case Downsampling._4xBox: + descriptor.width = Mathf.Max(1, descriptor.width / 4); + descriptor.height = Mathf.Max(1, descriptor.height / 4); + break; + } + } + + private int GetDownsamplePassIndex() + { + return _downSampling == Downsampling._4xBox ? 1 : 0; + } + + public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) + { + UniversalCameraData cameraData = frameData.Get(); + if (!IsSupportedCamera(cameraData.cameraType) || _renderMaskMat == null) + return; + + UniversalResourceData resourceData = frameData.Get(); + if (!resourceData.activeColorTexture.IsValid()) + return; + + UniversalRenderingData universalRenderingData = frameData.Get(); + UniversalLightData lightData = frameData.Get(); + + TextureDesc maskDescriptor = renderGraph.GetTextureDesc(resourceData.activeColorTexture); + maskDescriptor.name = "DisturbanceMaskRT"; + maskDescriptor.colorFormat = GraphicsFormat.R16G16_SFloat; + maskDescriptor.depthBufferBits = DepthBits.None; + maskDescriptor.clearBuffer = true; + maskDescriptor.clearColor = _clearDisturbanceMaskColor; + + TextureHandle maskTexture = renderGraph.CreateTexture(maskDescriptor); + using (var builder = renderGraph.AddRasterRenderPass("DisturbanceRender", out var passData)) + { + DrawingSettings drawingSettings = RenderingUtils.CreateDrawingSettings( + _shaderTag, + universalRenderingData, + cameraData, + lightData, + cameraData.defaultOpaqueSortFlags); + FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.all); + RendererListParams rendererListParameters = new RendererListParams( + universalRenderingData.cullResults, + drawingSettings, + filteringSettings); + + passData.rendererListHandle = renderGraph.CreateRendererList(rendererListParameters); + builder.UseRendererList(passData.rendererListHandle); + builder.SetRenderAttachment(maskTexture, 0, AccessFlags.ReadWrite); + + if (resourceData.activeDepthTexture.IsValid()) + builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.ReadWrite); + + if (_downSampling == Downsampling.None) + builder.SetGlobalTextureAfterPass(maskTexture, DisturbanceMaskTex); + + builder.SetRenderFunc(static (RenderGraphMaskPassData data, RasterGraphContext context) => + { + context.cmd.DrawRendererList(data.rendererListHandle); + }); + } + + if (_downSampling == Downsampling.None) + return; + + TextureDesc downsampleDescriptor = maskDescriptor; + downsampleDescriptor.name = "MaskDownCopyRT"; + downsampleDescriptor.clearBuffer = false; + ApplyDownsampling(ref downsampleDescriptor); + + TextureHandle downsampleTexture = renderGraph.CreateTexture(downsampleDescriptor); + + if (_downSampling == Downsampling._4xBox) + _renderMaskMat.SetFloat(SampleOffset, 2); + + RenderGraphUtils.BlitMaterialParameters blitParameters = + new RenderGraphUtils.BlitMaterialParameters(maskTexture, downsampleTexture, _renderMaskMat, GetDownsamplePassIndex()); + blitParameters.sourceTexturePropertyID = CameraTexture; + + renderGraph.AddBlitPass(blitParameters, "DisturbanceMaskDownsample"); + SetGlobalTextureAfterPass(renderGraph, downsampleTexture, DisturbanceMaskTex, "Set Disturbance Mask"); + } +#endif + + #if UNIVERSAL_RP_13_1_2_OR_NEWER + + public void SetUp ( RTHandle cameraRTHandle ) + { +#if !UNITY_6000_3_OR_NEWER || (URP_COMPATIBILITY_MODE && !UNITY_6000_4_OR_NEWER) +#pragma warning disable CS0618 + + RenderTextureDescriptor descrip = cameraRTHandle.rt.descriptor; + + descrip.colorFormat = RenderTextureFormat.RGHalf; + descrip.depthBufferBits = 0; + RenderingUtils.ReAllocateIfNeeded(ref _DisturbanceMaskRTHandle, descrip, name: "DisturbanceMaskRT"); + + + switch (_downSampling) + { + case Downsampling._2xBilinear: + descrip.width /= 2; + descrip.height /= 2; + break; + case Downsampling._4xBilinear: + descrip.width /= 4; + descrip.height /= 4; + break; + case Downsampling._4xBox: + descrip.width /= 4; + descrip.height /= 4; + break; + } + if (_downSampling != Downsampling.None) + RenderingUtils.ReAllocateIfNeeded(ref _DownRT, descrip, name:"MaskDownCopyRT"); +#pragma warning restore CS0618 +#endif + } + #else +#if !UNITY_6000_3_OR_NEWER || (URP_COMPATIBILITY_MODE && !UNITY_6000_4_OR_NEWER) + //在AddPass之前触发 + + public void SetUpDisturbanceMask(RenderTextureDescriptor descrip ,CommandBuffer cmd) + { + + descrip.colorFormat = RenderTextureFormat.RGHalf; + descrip.depthBufferBits = 0; + cmd.GetTemporaryRT(_DisturbanceMaskRTID, descrip,FilterMode.Bilinear); + + switch (_downSampling) + { + case Downsampling._2xBilinear: + descrip.width /= 2; + descrip.height /= 2; + break; + case Downsampling._4xBilinear: + descrip.width /= 4; + descrip.height /= 4; + break; + case Downsampling._4xBox: + descrip.width /= 4; + descrip.height /= 4; + break; + } + if (_downSampling != Downsampling.None) + cmd.GetTemporaryRT(_DownRTID, descrip,FilterMode.Bilinear); + } +#endif + #endif + +#if !UNITY_6000_3_OR_NEWER || (URP_COMPATIBILITY_MODE && !UNITY_6000_4_OR_NEWER) +#pragma warning disable CS0618, CS0672 + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) + { + _Filtering = new FilteringSettings(RenderQueueRange.all); + #if UNIVERSAL_RP_13_1_2_OR_NEWER + _cameraDepthRTHandle = renderingData.cameraData.renderer.cameraDepthTargetHandle; + #else + _cameraDepthRTHandle = renderingData.cameraData.renderer.cameraDepthTarget; + SetUpDisturbanceMask(renderingData.cameraData.cameraTargetDescriptor,cmd); + #endif + + } + + public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) + { +#if UNIVERSAL_RP_13_1_2_OR_NEWER + ConfigureTarget(_DisturbanceMaskRTHandle, _cameraDepthRTHandle); +#else + ConfigureTarget(_DisturbanceMaskRTID, _cameraDepthRTHandle); + +#endif + //将RT清空 + ConfigureClear(ClearFlag.Color, _clearDisturbanceMaskColor); + } + + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + + if (!(renderingData.cameraData.cameraType == CameraType.Game || renderingData.cameraData.cameraType == CameraType.SceneView)) + return; + + if (!_renderMaskMat) + { + return; + } + + var DisturbanceDraw = CreateDrawingSettings(_shaderTag, ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags); + + CommandBuffer cmd = CommandBufferPool.Get(); + using (new ProfilingScope(cmd, _profilingSampler)) + { + context.DrawRenderers(renderingData.cullResults, ref DisturbanceDraw, ref _Filtering); + +#if UNIVERSAL_RP_13_1_2_OR_NEWER + if (_downSampling == Downsampling.None) + { + cmd.SetGlobalTexture(DisturbanceMaskTex, _DisturbanceMaskRTHandle); + } + else + { + _renderMaskMat.SetTexture(CameraTexture, _DisturbanceMaskRTHandle); + cmd.SetRenderTarget((RenderTargetIdentifier)_DownRT); + + switch (_downSampling) + { + case Downsampling._2xBilinear: + Blitter.BlitTexture(cmd, _DisturbanceMaskRTHandle, Vector2.one, _renderMaskMat, 0); + break; + case Downsampling._4xBilinear: + Blitter.BlitTexture(cmd, _DisturbanceMaskRTHandle, Vector2.one, _renderMaskMat, 0); + break; + case Downsampling._4xBox: + _renderMaskMat.SetFloat(SampleOffset, 2); + Blitter.BlitTexture(cmd, _DisturbanceMaskRTHandle, Vector2.one, _renderMaskMat, 1); + break; + } + + cmd.SetGlobalTexture(DisturbanceMaskTex, _DownRT); + } + +#else + + if (_downSampling == Downsampling.None) + { + cmd.SetGlobalTexture(DisturbanceMaskTex, _DisturbanceMaskRTHandle); + } + else + { + // cmd.SetGlobalTexture(_DisturbanceMaskRTID, _DisturbanceMaskRTHandle); + //Bug:在非播放状态时,_DisturbanceMaskRTID在这里会经常丢失。造成画面闪烁。但是,只要有一个DistortObject在Scene中,并LockInspector,就不会闪烁,非常奇怪。 + cmd.SetGlobalTexture(CameraTexture, _DisturbanceMaskRTHandle); + // _renderMaskMat.SetTexture(CameraTexture, Shader.GetGlobalTexture(_DisturbanceMaskRTID)); + cmd.SetRenderTarget(_DownRT); + switch (_downSampling) + { + case Downsampling._2xBilinear: + // Blitter.BlitTexture(cmd, _DisturbanceMaskRTHandle, _DownRT, _renderMaskMat, 0); + // cmd.Blit(_DisturbanceMaskRTHandle, _DownRT, _renderMaskMat, 0); + // cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _renderMaskMat, 0, 2); + Blit(cmd, _DisturbanceMaskRTHandle,_DownRT,_renderMaskMat,0); + break; + case Downsampling._4xBilinear: + // Blitter.BlitTexture(cmd, _DisturbanceMaskRTHandle, _DownRT, _renderMaskMat, 0); + // cmd.Blit(_DisturbanceMaskRTHandle, _DownRT, _renderMaskMat, 0); + // cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _renderMaskMat, 0, 2); + Blit(cmd, _DisturbanceMaskRTHandle,_DownRT,_renderMaskMat,0); + break; + case Downsampling._4xBox: + _renderMaskMat.SetFloat(SampleOffset, 2); + // Blitter.BlitTexture(cmd, _DisturbanceMaskRTHandle, _DownRT, _renderMaskMat, 1); + // cmd.Blit(_DisturbanceMaskRTHandle, _DownRT, _renderMaskMat, 1); + // cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _renderMaskMat, 0, 3); + Blit(cmd, _DisturbanceMaskRTHandle,_DownRT,_renderMaskMat,1); + break; + } + + cmd.SetGlobalTexture(DisturbanceMaskTex, _DownRT); + } +#endif + + } + context.ExecuteCommandBuffer(cmd); + CommandBufferPool.Release(cmd); + } +#pragma warning restore CS0618, CS0672 +#endif + + #if !UNIVERSAL_RP_13_1_2_OR_NEWER && (!UNITY_6000_3_OR_NEWER || (URP_COMPATIBILITY_MODE && !UNITY_6000_4_OR_NEWER)) + // Cleanup any allocated resources that were created during the execution of this render pass. + public override void OnCameraCleanup(CommandBuffer cmd) + { + cmd.ReleaseTemporaryRT(_DisturbanceMaskRTID); + if (_downSampling != Downsampling.None) + cmd.ReleaseTemporaryRT(_DownRTID); + } + + //JustForSimple + public void Dispose() + { + } + #else + + public void Dispose() + { + _DisturbanceMaskRTHandle?.Release(); + _DownRT?.Release(); + } + #endif + } +} diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/DisturbanceMaskRenderPass.cs.meta b/Packages/NB_FX/NBPostProcessing/Runtime/DisturbanceMaskRenderPass.cs.meta new file mode 100644 index 00000000..22706f6c --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/DisturbanceMaskRenderPass.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1e411db03f9f4d85aa8a5e485158c961 +timeCreated: 1757141532 \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcess.cs b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcess.cs new file mode 100644 index 00000000..5f0efaec --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcess.cs @@ -0,0 +1,185 @@ +#if !UNITY_6000_3_OR_NEWER || (URP_COMPATIBILITY_MODE && !UNITY_6000_4_OR_NEWER) +#define NB_URP_COMPATIBILITY_PATH +#endif + +// using ConfigSystem.MConfig; +// using Sirenix.OdinInspector; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace NBShader +{ + public class NBPostProcess : ScriptableRendererFeature + { + private NBPostProcessRenderPass _renderPass; + private DisturbanceMaskRenderPass _disturbanceMaskRenderPass; + private ScreenColorRenderPass _screenColorRenderPass; + private RenderCameraOpaqueDistortObjectPass _renderCameraOpaqueDistortObjectPass; + + + public static Material NBPostProcessMaterial; + + //public MaskFormat maskFormat = MaskFormat.RG32; + public Downsampling downSampling = Downsampling.None; + + private Material _disturbanceDownSampleMat; + private Material _screenColorDownSampleMat; + private float _screenHeight; + private ProfilingSampler _profilingSampler; + + // private PostProcessingManager manager;-+ + static Mesh s_FullscreenTriangle; + /// + /// A fullscreen triangle mesh.抄自Unity的后处理包,拿到一个全屏的Triangle。 + /// + static Mesh fullscreenTriangle; + + + private bool canFind = false; + +#if UNIVERSAL_RP_17_0_OR_NEWER + private static bool IsCompatibilityModeEnabled() + { + return GraphicsSettings.GetRenderPipelineSettings().enableRenderCompatibilityMode; + } +#endif + + public override void Create() + { + + if (Shader.Find("XuanXuan/ColorBlit") == null || + Shader.Find("XuanXuan/Postprocess/NBPostProcessUber") == null) + { + canFind = false; + return; + } + else + { + canFind = true; + } + + #if UNIVERSAL_RP_13_1_2_OR_NEWER + _screenColorDownSampleMat = CoreUtils.CreateEngineMaterial(Shader.Find("XuanXuan/ColorBlit")); + #else + _screenColorDownSampleMat = CoreUtils.CreateEngineMaterial(Shader.Find("XuanXuan/ColorBufferBlit")); + #endif + _screenColorRenderPass = new ScreenColorRenderPass(_screenColorDownSampleMat, downSampling); + _screenColorRenderPass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents; + + + _profilingSampler = new ProfilingSampler("DisturbanceRender"); + _disturbanceDownSampleMat = CoreUtils.CreateEngineMaterial(Shader.Find("XuanXuan/ColorBlit")); + _disturbanceMaskRenderPass = new DisturbanceMaskRenderPass(_profilingSampler,_disturbanceDownSampleMat,downSampling); + _disturbanceMaskRenderPass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents; + + _renderCameraOpaqueDistortObjectPass = new RenderCameraOpaqueDistortObjectPass(); + _renderCameraOpaqueDistortObjectPass.renderPassEvent = RenderPassEvent.BeforeRenderingTransparents; + + #if !UNIVERSAL_RP_13_1_2_OR_NEWER + _profilingSampler = new ProfilingSampler("DisturbanceDownRTBlit"); + #endif + + if (fullscreenTriangle == null) + { + /*UNITY_NEAR_CLIP_VALUE*/ + float nearClipZ = -1; + if (SystemInfo.usesReversedZBuffer) + nearClipZ = 1; + + fullscreenTriangle = new Mesh(); + fullscreenTriangle.vertices = GetFullScreenTriangleVertexPosition(nearClipZ); + fullscreenTriangle.uv = GetFullScreenTriangleTexCoord(); + fullscreenTriangle.triangles = new int[3] { 0, 1, 2 }; + } + + // Shader shader = Shader.Find("XuanXuan/Postprocess/NBPostProcessUber"); + NBPostProcessMaterial = CoreUtils.CreateEngineMaterial(Shader.Find("XuanXuan/Postprocess/NBPostProcessUber")); + + PostProcessingManager.InitMat(); + + + _renderPass = new NBPostProcessRenderPass(NBPostProcessMaterial,fullscreenTriangle); + _renderPass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents; + + } + +#if UNIVERSAL_RP_13_1_2_OR_NEWER && NB_URP_COMPATIBILITY_PATH +#pragma warning disable CS0618, CS0672 + public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData) + { +#if UNIVERSAL_RP_17_0_OR_NEWER + if (!IsCompatibilityModeEnabled()) + return; +#endif + + if ((renderingData.cameraData.cameraType == CameraType.Game || + renderingData.cameraData.cameraType == CameraType.SceneView) && canFind) + { + + _disturbanceMaskRenderPass.ConfigureInput(ScriptableRenderPassInput.Color); + _disturbanceMaskRenderPass.SetUp(renderer.cameraColorTargetHandle); + + _screenColorRenderPass.ConfigureInput(ScriptableRenderPassInput.Color); + _screenColorRenderPass.SetUp(renderer.cameraColorTargetHandle); + } + } +#pragma warning restore CS0618, CS0672 + +#endif + + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) + { + if ((renderingData.cameraData.cameraType == CameraType.Game || + renderingData.cameraData.cameraType == CameraType.SceneView) && canFind) + { + + #if !UNIVERSAL_RP_13_1_2_OR_NEWER + _screenColorRenderPass.ConfigureInput(ScriptableRenderPassInput.Color); + _screenColorRenderPass.SetUp(renderer); + #endif + renderer.EnqueuePass(_renderCameraOpaqueDistortObjectPass); + renderer.EnqueuePass(_screenColorRenderPass); + renderer.EnqueuePass(_disturbanceMaskRenderPass); + renderer.EnqueuePass(_renderPass); + } + } + + // Should match Common.hlsl + static Vector3[] GetFullScreenTriangleVertexPosition(float z /*= UNITY_NEAR_CLIP_VALUE*/) + { + var r = new Vector3[3]; + for (int i = 0; i < 3; i++) + { + Vector2 uv = new Vector2((i << 1) & 2, i & 2); + r[i] = new Vector3(uv.x * 2.0f - 1.0f, uv.y * 2.0f - 1.0f, z); + } + return r; + } + + // Should match Common.hlsl + static Vector2[] GetFullScreenTriangleTexCoord() + { + var r = new Vector2[3]; + for (int i = 0; i < 3; i++) + { + if (SystemInfo.graphicsUVStartsAtTop) + r[i] = new Vector2((i << 1) & 2, 1.0f - (i & 2)); + else + r[i] = new Vector2((i << 1) & 2, i & 2); + } + return r; + } + + protected override void Dispose(bool disposing) + { + CoreUtils.Destroy(_disturbanceDownSampleMat); + //CoreUtils.Destroy(NBPostProcessMaterial); + _disturbanceMaskRenderPass?.Dispose(); + CoreUtils.Destroy(_screenColorDownSampleMat); + _screenColorRenderPass?.Dispose(); + + + } + } +} diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcess.cs.meta b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcess.cs.meta new file mode 100644 index 00000000..e1753857 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcess.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d5a1f9350d8fc2c46a372955ef0e73b5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcessRenderPass.cs b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcessRenderPass.cs new file mode 100644 index 00000000..b05e01fa --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcessRenderPass.cs @@ -0,0 +1,100 @@ +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; +#if UNIVERSAL_RP_17_0_OR_NEWER +using UnityEngine.Rendering.RenderGraphModule; +#endif +namespace NBShader +{ + public class NBPostProcessRenderPass : ScriptableRenderPass + { + private ProfilingSampler _profilingSampler; + public static Material _material; + public Mesh _fullScreenMesh; + private static readonly int ScreenColorCopy = Shader.PropertyToID("_ScreenColorCopy1"); + private static readonly int DisturbanceMaskTex = Shader.PropertyToID("_DisturbanceMaskTex"); + + public NBPostProcessFlags _shaderFlag => PostProcessingManager.flags; + + private Vector4 _lastOutlineProps; + public Vector4 outLinePorps = Vector4.one; + +#if UNIVERSAL_RP_17_0_OR_NEWER + private class RenderGraphPassData + { + public TextureHandle activeColorTexture; + public Material material; + public Mesh fullscreenMesh; + } + + private static bool IsSupportedCamera(CameraType cameraType) + { + return cameraType == CameraType.Game || cameraType == CameraType.SceneView; + } + + public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) + { + UniversalCameraData cameraData = frameData.Get(); + if (!IsSupportedCamera(cameraData.cameraType) || _material == null || _fullScreenMesh == null) + return; + + UniversalResourceData resourceData = frameData.Get(); + if (!resourceData.activeColorTexture.IsValid()) + return; + + using (var builder = renderGraph.AddRasterRenderPass("NBPostProcess", out var passData)) + { + passData.activeColorTexture = resourceData.activeColorTexture; + passData.material = _material; + passData.fullscreenMesh = _fullScreenMesh; + + builder.SetRenderAttachment(passData.activeColorTexture, 0, AccessFlags.ReadWrite); + builder.UseGlobalTexture(ScreenColorCopy, AccessFlags.Read); + builder.UseGlobalTexture(DisturbanceMaskTex, AccessFlags.Read); + builder.SetRenderFunc(static (RenderGraphPassData data, RasterGraphContext context) => + { + context.cmd.DrawMesh(data.fullscreenMesh, Matrix4x4.identity, data.material, 0, 0); + }); + } + } +#endif + +#if !UNITY_6000_3_OR_NEWER || (URP_COMPATIBILITY_MODE && !UNITY_6000_4_OR_NEWER) +#pragma warning disable CS0618, CS0672 + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + if (!(renderingData.cameraData.cameraType == CameraType.Game || renderingData.cameraData.cameraType == CameraType.SceneView)) + return; + if(_material == null) return; + if(_fullScreenMesh == null) return; + + // if(!_shaderFlag.CheckFlagBits(NBPostProcessFlags.FLAG_BIT_NB_POSTPROCESS_ON))return;//Disturbance需要执行 + + //ConfigureTarget() + CommandBuffer cmdBuffer = CommandBufferPool.Get(); + cmdBuffer.Clear(); + // cmdBuffer.name = "NBPostProcess"; + + using (new ProfilingScope(cmdBuffer,_profilingSampler)) + { + cmdBuffer.DrawMesh(_fullScreenMesh, Matrix4x4.identity, _material, 0, 0); + } + + context.ExecuteCommandBuffer(cmdBuffer); + CommandBufferPool.Release(cmdBuffer); + } +#pragma warning restore CS0618, CS0672 +#endif + + public NBPostProcessRenderPass(Material mat,Mesh mesh) + { + _material = mat; + _fullScreenMesh = mesh; + _profilingSampler ??= new ProfilingSampler("NBPostProcess"); +#if UNIVERSAL_RP_17_0_OR_NEWER + requiresIntermediateTexture = true; +#endif + + } + } +} diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcessRenderPass.cs.meta b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcessRenderPass.cs.meta new file mode 100644 index 00000000..f6116ade --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostProcessRenderPass.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2a20551d205e487f89b91897e9cb7a43 +timeCreated: 1757141611 \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/NBPostprocessFlags.cs b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostprocessFlags.cs new file mode 100644 index 00000000..80ec72f0 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostprocessFlags.cs @@ -0,0 +1,40 @@ +using UnityEngine; + +namespace NBShader +{ + public class NBPostProcessFlags : ShaderFlagsBase + { + public const string FlagsName = "_NBPostProcessFlags"; + public static int FlagsId = Shader.PropertyToID(FlagsName); + + public override int GetShaderFlagsId(int index = 0) + { + return FlagsId; + } + + protected override string GetShaderFlagsName(int index = 0) + { + return FlagsName; + } + + public NBPostProcessFlags(Material material = null) : base(material) + { + } + + public const int FLAG_BIT_NB_POSTPROCESS_ON = 1 << 0; + public const int FLAG_BIT_DISTORT_SPEED = 1 << 1; + public const int FLAG_BIT_OVERLAYTEXTURE = 1 << 2; + public const int FLAG_BIT_FLASH = 1 << 3; + public const int FLAG_BIT_CHORATICABERRAT = 1 << 4; + public const int FLAG_BIT_RADIALBLUR = 1 << 5; + public const int FLAG_BIT_VIGNETTE = 1 << 6; + public const int FLAG_BIT_OVERLAYTEXTURE_POLLARCOORD = 1 << 7; + public const int FLAG_BIT_OVERLAYTEXTURE_MASKMAP = 1 << 8; + public const int FLAG_BIT_POST_DISTORT_SCREEN_UV = 1 << 9; //默认来自于PolarUV + public const int FLAG_BIT_RADIALBLUR_BY_DISTORT = 1 << 10; //默认来自于PolarUV + public const int FLAG_BIT_CHORATICABERRAT_BY_DISTORT = 1 << 11; //默认来自于PolarUV + public const int FLAG_BIT_FLASHTEXTURE_POLLARCOORD = 1 << 12; + + + } +} \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/NBPostprocessFlags.cs.meta b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostprocessFlags.cs.meta new file mode 100644 index 00000000..12f79afb --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/NBPostprocessFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be6a95b97f4bc3846bdada66138f6da1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingController.cs b/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingController.cs new file mode 100644 index 00000000..978d58a5 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingController.cs @@ -0,0 +1,518 @@ +using UnityEngine; +#if CINIMACHINE_3_0 +using Unity.Cinemachine; +#endif +#if UNITY_EDITOR +using UnityEditor.AnimatedValues; +using UnityEditor; +#endif + +namespace NBShader +{ + [ExecuteInEditMode] + public class PostProcessingController : MonoBehaviour + { + #if UNITY_EDITOR + public AnimBool[] AnimBools = new AnimBool[10]; + #endif + [SerializeField] + private PostProcessingManager _manager; + + public int index + { + get + { + return _index; + } + } + private int _index; + public void SetIndex(int controllerIndex) + { + _index = controllerIndex; + } + + public Vector2 customScreenCenterPos = new Vector2(0.5f, 0.5f); + private Vector2 _lastCustomScreenCenterPos = new Vector2(0.5f, 0.5f); + public bool chromaticAberrationToggle = false; + public bool caFromDistort = false; + public float chromaticAberrationIntensity = 0.2f; + public float chromaticAberrationPos = 0.5f; + public float chromaticAberrationRange = 0.5f; + public bool distortSpeedToggle = false; + public bool distortScreenUVMode = false; + public Texture2D distortSpeedTexture; + public float distortTextureMidValue = 1; + public Vector4 distortSpeedTexSt = new Vector4(30,1,0,0); + public float distortSpeedIntensity = 1f; + public float distortSpeedPosition = 0.5f; + public float distortSpeedRange = 1f; + public float distortSpeedMoveSpeedX = 0.1f; + public float distortSpeedMoveSpeed = -0.5f;//因为老的做法是没有X偏移的,只有Y的偏移,不改变量兼容老做法。 + private readonly int _distortSpeedTextureID = Shader.PropertyToID("_SpeedDistortMap"); + private readonly int _distortSpeedTextureStID = Shader.PropertyToID("_SpeedDistortMap_ST"); + public bool radialBlurToggle = false; + public bool radialBlurFromDistort = false; + [Range(1,12)] + public int radialBlurSampleCount = 4; + public float radialBlurIntensity = 1; + public float radialBlurPos = 0.5f; + public float radialBlurRange = 0.5f; + #if CINIMACHINE_3_0 + public bool cameraShakeToggle = false; + public CinemachineCamera cinemachineCamera; + public float cameraShakeIntensity; + #endif + + public bool overlayTextureToggle = false; + public bool overlayTexturePolarCoordMode = false; + public Texture2D overlayTexture; + private readonly int _overlayTextureID = Shader.PropertyToID("_TextureOverlay"); + private readonly int _overlayTextureStID = Shader.PropertyToID("_TextureOverlay_ST"); + private readonly int _textureOverlayAnimProperty = Shader.PropertyToID("_TextureOverlayAnim"); + private readonly int _textureOverlayMaskProperty = Shader.PropertyToID("_TextureOverlayMask"); + private readonly int _textureOverlayMaskStProperty = Shader.PropertyToID("_TextureOverlayMask_ST"); + public Vector4 overlayTextureSt = new Vector4(1, 1, 0, 0); + public Vector2 overlayTextureAnim = new Vector2(0, 0); + public float overlayTextureIntensity = 1f; + public Texture2D overlayMaskTexture; + public Vector4 overlayMaskTextureSt; + + public bool flashToggle = false; + [Range(0,1)] + public float flashIntensity = 1f; + [Range(0,1)] + public float flashInvertIntensity = 0f; + public float flashDeSaturateIntensity = 1f; + public float flashGradientRange = 0.25f; + public float flashContrast = 0.5f; + [ColorUsage(false, true)] + public Color flashColor = new Color(2f,2f,2f,1f); + [ColorUsage(false, true)] + public Color blackFlashColor = new Color(0f,0f,0f,1f); + private readonly int _flashTextureProperty = Shader.PropertyToID("_FlashTexture"); + public Texture2D flashTexture; + public Vector4 flashTextureScaleOffset = new Vector4(10f,0.1f,0f,0f); + public bool flashTexturePolarCoordMode = true; + public Vector2 flashVec = new Vector2(0, 0.05f); + public Vector2 flashVecZW = new Vector2(0.2f, 0.2f);//FlashTextureMask + public float flashTextureIntensity = 0.5f; + + public bool vignetteToggle = false; + public Color vignetteColor = Color.black; + private readonly int _vignetteColorID = Shader.PropertyToID("_VignetteColor"); + public float vignetteIntensity = 1; + public float vignetteRoundness = 1; + public float vignetteSmothness = 10; + [Range(0,1)] + public float vignetteFill = 0f; + + + public void InitController() + { + if (this.isActiveAndEnabled == false) + { + return; + } + + _manager = PostProcessingManager.Instance; + + _manager.InitController(this); + InitAllSettings(); + + } + + void InitAllSettings() + { + SetScreenCenterPos(); + SetToggles(); + SetUVFromDistort(); + SetTexture(); + #if CINIMACHINE_3_0 + InitCinemachineCamera(); + #endif + } + + void SetScreenCenterPos() + { + PostProcessingManager.customScreenCenterPos = customScreenCenterPos; + _lastCustomScreenCenterPos = customScreenCenterPos; + } + + void SetUVFromDistort() + { + PostProcessingManager.isDistortScreenUVMode = distortScreenUVMode; + PostProcessingManager.isCaByDistort = caFromDistort; + PostProcessingManager.isRadialBlurByDistort = radialBlurFromDistort; + } + + private void SetTexture() + { + if(PostProcessingManager.material == null) return; + if (distortSpeedToggle) + { + if (distortSpeedTexture != null) + { + PostProcessingManager.material.SetTexture(_distortSpeedTextureID, distortSpeedTexture); + PostProcessingManager.distortTextureMidValue = distortTextureMidValue; + } + else + { + PostProcessingManager.material.SetTexture(_distortSpeedTextureID, null); + } + } + + if (flashToggle&& flashTexture) + { + PostProcessingManager.material.SetTexture(_flashTextureProperty, flashTexture); + if (flashTexturePolarCoordMode) + { + PostProcessingManager.flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_FLASHTEXTURE_POLLARCOORD); + } + else + { + PostProcessingManager.flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_FLASHTEXTURE_POLLARCOORD); + } + } + else + { + PostProcessingManager.material.SetTexture(_flashTextureProperty, null); + PostProcessingManager.flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_FLASHTEXTURE_POLLARCOORD); + } + + if (overlayTextureToggle) + { + if (overlayTexturePolarCoordMode) + { + PostProcessingManager.flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_OVERLAYTEXTURE_POLLARCOORD); + } + else + { + PostProcessingManager.flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_OVERLAYTEXTURE_POLLARCOORD); + } + + if (overlayTexture) + { + Debug.Log("SetOverlayTexture"); + PostProcessingManager.material.SetTexture(_overlayTextureID,overlayTexture); + } + else + { + Debug.Log("ClearOverlayTexture"); + PostProcessingManager.material.SetTexture(_overlayTextureID,null); + } + + if (overlayMaskTexture) + { + Debug.Log("SetOverlayMaskTexture"); + PostProcessingManager.material.SetTexture(_textureOverlayMaskProperty,overlayMaskTexture); + PostProcessingManager.flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_OVERLAYTEXTURE_MASKMAP); + } + else + { + Debug.Log("ClearOverlayMaskTexture"); + PostProcessingManager.flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_OVERLAYTEXTURE_MASKMAP); + } + } + + } + + private void SetToggles() + { + SetBit(ref PostProcessingManager.chromaticAberrationToggles,index,chromaticAberrationToggle); + SetBit(ref PostProcessingManager.distortSpeedToggles,index,distortSpeedToggle); + #if CINIMACHINE_3_0 + SetBit(ref PostProcessingManager.cameraShakeToggles,index,cameraShakeToggle); + #endif + SetBit(ref PostProcessingManager.overlayTextureToggles,index,overlayTextureToggle); + SetBit(ref PostProcessingManager.flashToggles,index,flashToggle); + SetBit(ref PostProcessingManager.radialBlurToggles,index,radialBlurToggle); + SetBit(ref PostProcessingManager.vignetteToggles,index,vignetteToggle); + + #if UNITY_EDITOR + SetTexture(); + #endif + + } + + private void ClearToggles() + { + SetBit(ref PostProcessingManager.chromaticAberrationToggles,index,false); + SetBit(ref PostProcessingManager.distortSpeedToggles,index,false); + #if CINIMACHINE_3_0 + SetBit(ref PostProcessingManager.cameraShakeToggles,index,false); + #endif + SetBit(ref PostProcessingManager.overlayTextureToggles,index,false); + SetBit(ref PostProcessingManager.flashToggles,index,false); + SetBit(ref PostProcessingManager.radialBlurToggles,index,false); + SetBit(ref PostProcessingManager.vignetteToggles,index,false); + } + + private bool _lastChormaticAberrationToggle = false; + private bool _lastDistortSpeedToggle = false; + #if CINIMACHINE_3_0 + private bool _lastCamerashakeToggle = false; + #endif + private bool _lastOverlayTextureToggle = false; + private bool _lastFlashToggle= false; + private bool _lastRadialBlurToggle= false; + private bool _lastVignetteToggle= false; + + bool checkIfToggleChanged(ref bool lastTogggle, bool currentToggle) + { + if (lastTogggle != currentToggle) + { + lastTogggle = currentToggle; + return true; + } + else + { + return false; + } + } + + + + private static void SetBit(ref int bit, int index,bool bitToggle) + { + if (bitToggle) + { + bit |= (1 << index); + } + else + { + bit &= ~(1 << index); + } + } + + #if UNITY_EDITOR + void FindManager() + { + UnityEditor.Selection.activeObject = _manager.gameObject; + } + #endif + + #if CINIMACHINE_3_0 + #if UNITY_EDITOR + public void FindVirtualCamera() + { + UnityEditor.Selection.activeObject = _manager.currentVirtualCamera; + } + #endif + + public void InitCinemachineCamera() + { + if (cinemachineCamera) + { + if (!cinemachineCamera.gameObject.TryGetComponent(out var _perlin)) + { + _perlin = cinemachineCamera.gameObject.AddComponent(); + } + + #if UNITY_EDITOR + if (_perlin) + { + if (_perlin.NoiseProfile == null) + { + _perlin.NoiseProfile = + UnityEditor.AssetDatabase.LoadAssetAtPath( + "Packages/com.xuanxuan.nb.fx/NBPostProcessing/3DPostionShake.asset"); + _perlin.FrequencyGain = 5f; //做一个自定义 + } + _perlin.AmplitudeGain = 0f; //一开始先不要震动 + } + + if (_manager) + { + _manager.currentVirtualCamera = cinemachineCamera; + } + #endif + } + + } + #endif + + + private void OnEnable() + { + // Debug.Log("InitController"); + InitController(); + #if UNITY_EDITOR + // 注册编辑器帧更新事件 + EditorApplication.update += ControllerEditorUpdate; + _manager.ReRegistEditorUpdate();//保证Manager的注册在最后 + #endif + } + + private void OnDisable() + { + // Debug.Log("EndController"); + EndController(); + #if UNITY_EDITOR + // 注册编辑器帧更新事件 + EditorApplication.update -= ControllerEditorUpdate; + #endif + } + + bool isFirstUpdate = true; + // Update is called once per frame + void Update() + { + if (isFirstUpdate) + { + isFirstUpdate = false; + return; + } + if(!PostProcessingManager.material) return; + //#if UNITY_EDITOR + //Odin的ToggleGroup和OnValueChange功能冲突,导致不一定生效。不好调试。所以用手动的方式更新。 + bool isToggleChanged = false; + isToggleChanged |= checkIfToggleChanged(ref _lastChormaticAberrationToggle, chromaticAberrationToggle); + isToggleChanged |= checkIfToggleChanged(ref _lastDistortSpeedToggle, distortSpeedToggle); + #if CINIMACHINE_3_0 + isToggleChanged |= checkIfToggleChanged(ref _lastCamerashakeToggle, cameraShakeToggle); + #endif + isToggleChanged |= checkIfToggleChanged(ref _lastOverlayTextureToggle, overlayTextureToggle); + isToggleChanged |= checkIfToggleChanged(ref _lastFlashToggle, flashToggle); + isToggleChanged |= checkIfToggleChanged(ref _lastRadialBlurToggle, radialBlurToggle); + isToggleChanged |= checkIfToggleChanged(ref _lastVignetteToggle, vignetteToggle); + if (isToggleChanged) + { + SetToggles(); + } + //#endif + + if (customScreenCenterPos != _lastCustomScreenCenterPos) + { + SetScreenCenterPos(); + } + + + if (chromaticAberrationToggle) + { + PostProcessingManager.chromaticAberrationIntensity = + Mathf.Max(PostProcessingManager.chromaticAberrationIntensity, chromaticAberrationIntensity); + PostProcessingManager.chromaticAberrationPos = + Mathf.Max(PostProcessingManager.chromaticAberrationPos, chromaticAberrationPos); + PostProcessingManager.chromaticAberrationRange = + Mathf.Max(PostProcessingManager.chromaticAberrationRange, chromaticAberrationRange); + } + + if (distortSpeedToggle) + { + if (index == PostProcessingManager.laseUpdateControllerIndex) + { + //只有这里才会更新Scale + PostProcessingManager.material.SetVector(_distortSpeedTextureStID, distortSpeedTexSt); + } + + PostProcessingManager.distortSpeedIntensity = + Mathf.Max(PostProcessingManager.distortSpeedIntensity, distortSpeedIntensity); + PostProcessingManager.distortSpeedPosition = + Mathf.Max(PostProcessingManager.distortSpeedPosition, distortSpeedPosition); + PostProcessingManager.distortSpeedRange = + Mathf.Max(PostProcessingManager.distortSpeedRange, distortSpeedRange); + PostProcessingManager.distortSpeedMoveSpeedX = + Mathf.Abs(PostProcessingManager.distortSpeedMoveSpeedX) > Mathf.Abs(distortSpeedMoveSpeedX) + ? PostProcessingManager.distortSpeedMoveSpeedX + : distortSpeedMoveSpeedX; + PostProcessingManager.distortSpeedMoveSpeedY = + Mathf.Abs(PostProcessingManager.distortSpeedMoveSpeedY) > Mathf.Abs(distortSpeedMoveSpeed) + ? PostProcessingManager.distortSpeedMoveSpeedY + : distortSpeedMoveSpeed; + } + + #if CINIMACHINE_3_0 + if (cameraShakeToggle) + { + PostProcessingManager.cameraShakeIntensity = + Mathf.Max(PostProcessingManager.cameraShakeIntensity, cameraShakeIntensity); + + } + #endif + + if (overlayTextureToggle) + { + if (index == PostProcessingManager.laseUpdateControllerIndex) + { + PostProcessingManager.material.SetVector(_overlayTextureStID, overlayTextureSt); + PostProcessingManager.material.SetVector(_textureOverlayMaskStProperty, overlayMaskTextureSt); + PostProcessingManager.material.SetVector(_textureOverlayAnimProperty,overlayTextureAnim); + } + + PostProcessingManager.overlayTextureIntensity = Mathf.Max(PostProcessingManager.overlayTextureIntensity, + overlayTextureIntensity); + } + + if (flashToggle) + { + PostProcessingManager.flashDesaturateIntensity = + Mathf.Max(PostProcessingManager.flashDesaturateIntensity, flashDeSaturateIntensity); + PostProcessingManager.flashInvertIntensity = + Mathf.Max(PostProcessingManager.flashInvertIntensity, flashInvertIntensity); + PostProcessingManager.flashIntensity = Mathf.Max(PostProcessingManager.flashIntensity, flashIntensity); + PostProcessingManager.flashContrast = + Mathf.Max(PostProcessingManager.flashContrast, flashContrast); + PostProcessingManager.flashGradientRange = Mathf.Max(PostProcessingManager.flashGradientRange, flashGradientRange); + PostProcessingManager.flashVec = new Vector4(flashVec.x,flashVec.y,flashVecZW.x,flashVecZW.y); + PostProcessingManager.flashTextureIntensity = Mathf.Max(PostProcessingManager.flashTextureIntensity, flashTextureIntensity); + PostProcessingManager.flashTextureScaleOffset = flashTextureScaleOffset; + + PostProcessingManager.flashColor = flashColor; + PostProcessingManager.blackFlashColor = blackFlashColor; + } + + if (radialBlurToggle) + { + PostProcessingManager.radialBlurIntensity = + Mathf.Max(PostProcessingManager.radialBlurIntensity, radialBlurIntensity); + PostProcessingManager.radialBlurSampleCount = Mathf.Max(PostProcessingManager.radialBlurSampleCount, + radialBlurSampleCount); + PostProcessingManager.radialBlurPos = Mathf.Max(PostProcessingManager.radialBlurPos, radialBlurPos); + PostProcessingManager.radialBlurRange = Mathf.Max(PostProcessingManager.radialBlurRange, radialBlurRange); + } + + if (vignetteToggle) + { + PostProcessingManager.vignetteIntensity = + Mathf.Max(PostProcessingManager.vignetteIntensity, vignetteIntensity); + PostProcessingManager.vignetteRoundness = Mathf.Max(PostProcessingManager.vignetteRoundness, vignetteRoundness); + PostProcessingManager.vignetteSmothness = Mathf.Max(PostProcessingManager.vignetteSmothness, vignetteSmothness); + PostProcessingManager.vignetteFill = Mathf.Max(PostProcessingManager.vignetteFill, vignetteFill); + if (index == PostProcessingManager.laseUpdateControllerIndex) + { + PostProcessingManager.material.SetColor(_vignetteColorID,vignetteColor); + } + } + + + } + + + void EndController() + { + ClearToggles(); + _manager.EndController(this); + } + + + #if UNITY_EDITOR + [UnityEditor.MenuItem("GameObject/创建NB后处理特效")] + static void CreatMenu() + { + GameObject Effect = new GameObject(); + Effect.name = "NBPostprocessController"; + PostProcessingController controller = Effect.AddComponent(); + + UnityEditor.Selection.activeObject = Effect; + } + + void ControllerEditorUpdate() + { + if (!Application.isPlaying) + { + Update(); + } + } + #endif + } +} diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingController.cs.meta b/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingController.cs.meta new file mode 100644 index 00000000..64bfbc70 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingController.cs.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 909ea7d136ae0c349a24f02cac1f5f71 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: + - manager: {instanceID: 0} + - distortSpeedTexture: {fileID: 2800000, guid: 7f808d0c8608b954d8f20cb4132c3049, type: 3} + - overlayTexture: {instanceID: 0} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingManager.cs b/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingManager.cs new file mode 100644 index 00000000..fbe599b7 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingManager.cs @@ -0,0 +1,727 @@ +using System; +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + +#if CINIMACHINE_3_0 +using Unity.Cinemachine; +#endif + +namespace NBShader +{ + + + [ExecuteAlways] + public class PostProcessingManager : MonoBehaviour + { + //单例实现 + private static PostProcessingManager _instance = null; + + public static PostProcessingManager Instance + { + get + { + if (_instance == null) + { + _instance = UnityObjectFindCompat.FindAny(); + if (_instance == null) + { + GameObject singletonObj = new GameObject(); + _instance = singletonObj.AddComponent(); + singletonObj.name = "NBPostProcessManager"; + if (Application.isPlaying) + { + DontDestroyOnLoad(singletonObj); + } + else + { + singletonObj.hideFlags = HideFlags.HideAndDontSave;//如果要调试可以去掉这个属性 + } + } + } + + return _instance; + } + } + + + private void Awake() + { + if (_instance == null) + { + _instance = this; + } + else + { + DestroyImmediate(this); + } + } + + // [ReadOnly] public Volume volume; + // private static VolumeProfile profile; + // [ReadOnly] + public static Material material + { + get { return NBPostProcess.NBPostProcessMaterial; } + } + + public static NBPostProcessFlags flags = new NBPostProcessFlags(); + + // public CinemachineBrain cameraBrain; + // public CinemachineVirtualCamera currentVirtualCamera; +#if CINIMACHINE_3_0 + public CinemachineCamera currentVirtualCamera; + private CinemachineBasicMultiChannelPerlin _perlin; +#endif + + public static void InitMat() + { + flags.SetMaterial(PostProcessingManager.material); + if (_instance) + { + _instance.ResetEffect(); + } + } + + private void OnEnable() + { +#if UNITY_EDITOR + if (_controllerIndexFlags > 0) + { + ReRegistEditorUpdate(); + } + else + { + EditorApplication.update += EditorUpdate; + } + // 注册编辑器帧更新事件 +#endif + + //重置Flag + flags = new NBPostProcessFlags(material); + flags.SetFlagBits(0); + } + + private void OnDisable() + { +#if UNITY_EDITOR + // 注册编辑器帧更新事件 + EditorApplication.update -= EditorUpdate; +#endif + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_NB_POSTPROCESS_ON); + } + + + // [ShowInInspector] + // #if UNITY_EDITOR + // [BinaryInt(8)] + // #endif + private int _controllerIndexFlags = 0; + + public static int laseUpdateControllerIndex; + + private int GetControllerIndex() + { + for (int i = 0; i < 31; i++) + { + if (((~_controllerIndexFlags) & (1 << i)) != 0) + { + _controllerIndexFlags |= (1 << i); + laseUpdateControllerIndex = i; + return i; + } + } + + return 32; + } + + private void ReleaseControllerIndex(int index) + { + _controllerIndexFlags &= ~(1 << index); + } + + private int CountBit(int bit) + { + int count = 0; + while (bit > 0) + { + bit = bit & (bit - 1); + count++; + } + + return count; + } + + //每次Controller触发Play都会触发Init + public void InitController(PostProcessingController controller) + { +#if CINIMACHINE_3_0 + if (controller.cinemachineCamera != null) + { + currentVirtualCamera = controller.cinemachineCamera; + _perlin = currentVirtualCamera.gameObject.GetComponent(); + } +#endif + + controller.SetIndex(GetControllerIndex()); + } + + public void EndController(PostProcessingController controller) + { +#if CINIMACHINE_3_0 + if (currentVirtualCamera == controller.cinemachineCamera) + { + currentVirtualCamera = null; + _perlin = null; + } +#endif + + ReleaseControllerIndex(controller.index); + controller.SetIndex(32); //设置32为关闭index + } + + private void EffectUpdater(Action initEffect, Action updateEffect, Action endEffect, ref bool lastIsEffect, + int effectToggles) + { + if (effectToggles > 0) + { + if (!lastIsEffect) + { + initEffect(); + } + + updateEffect(); + lastIsEffect = true; + } + else + { + if (lastIsEffect) + { + endEffect(); + lastIsEffect = false; + } + } + + + } + + private bool isFirstUpdate = true; + + private void ResetEffect() + { + if (_lastIsChromaticAberration) + { + EndChromaticAberration(); + _lastIsChromaticAberration = false; + } + + if (_lastIsRadialBlur) + { + EndRadialBlur(); + _lastIsRadialBlur = false; + } + + if (_lastIsDistortSpeed) + { + EndDistortSpeed(); + _lastIsDistortSpeed = false; + } + +#if CINIMACHINE_3_0 + if (_lastIsCameraShake) + { + EndCameraShake(); + _lastIsCameraShake = false; + } +#endif + + if (_lastIsOverlayTexture) + { + EndOverlayTexture(); + _lastIsOverlayTexture = false; + } + + if (_lastIsFlash) + { + EndFlash(); + _lastIsFlash = false; + } + + if (_lastIsVignette) + { + EndVignette(); + _lastIsVignette = false; + } + } + + private void LateUpdate() //晚于所有脚本触发。 + { + if (isFirstUpdate) + { + isFirstUpdate = false; + return; + } + + if (!material) return; + /* + #if UNITY_EDITOR + if (flags.GetMaterial() != PostProcessingManager.material) + { + flags.SetMaterial(PostProcessingManager.material); + } + #endif + */ + + if (_controllerIndexFlags == 0) + { + ResetEffect(); + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_NB_POSTPROCESS_ON); + return; + } + + EffectUpdater(InitChromaticAberration, UpdateChromaticAberration, EndChromaticAberration, + ref _lastIsChromaticAberration, chromaticAberrationToggles); + EffectUpdater(InitDistortSpeed, UpdateDistortSpeed, EndDistortSpeed, ref _lastIsDistortSpeed, + distortSpeedToggles); + EffectUpdater(InitRadialBlur, UpdateRadialBlur, EndRadialBlur, ref _lastIsRadialBlur, radialBlurToggles); + + bool isSetCustomScreenCenterPos = + (chromaticAberrationToggles | distortSpeedToggles | radialBlurToggles|flashToggles) > 0; + + if (isSetCustomScreenCenterPos) + { + material.SetVector(_customScreenCenterProperty, + new Vector4(customScreenCenterPos.x, customScreenCenterPos.y, 0, 0)); + } + +#if CINIMACHINE_3_0 + EffectUpdater(() => { }, UpdateCameraShake, EndCameraShake, ref _lastIsCameraShake, cameraShakeToggles); +#endif + EffectUpdater(InitOverlayTexture, UpdateOverlayTexture, EndOverlayTexture, ref _lastIsOverlayTexture, + overlayTextureToggles); + EffectUpdater(InitFlash, UpdateFlash, EndFlash, ref _lastIsFlash, flashToggles); + EffectUpdater(InitVignette, UpdateVignette, EndVignette, ref _lastIsVignette, vignetteToggles); + + bool hasEffect = + ( + chromaticAberrationToggles | + distortSpeedToggles | +#if CINIMACHINE_3_0 + cameraShakeToggles | +#endif + radialBlurToggles | + overlayTextureToggles | + flashToggles | + vignetteToggles + ) > 0; + + if (hasEffect) + { + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_NB_POSTPROCESS_ON); + } + else + { + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_NB_POSTPROCESS_ON); + } + } + + + private readonly int _customScreenCenterProperty = Shader.PropertyToID("_CustomScreenCenter"); + public static Vector2 customScreenCenterPos = new Vector2(0.5f, 0.5f); + + + + + #region 色散 + + //色散相关 + // private ChromaticAberration chromaticAberrationComp; + // private bool preserveChromaticAberrationActive; + // private float preserveChromaticAberrationIntensity; + private bool _lastIsChromaticAberration = false; + private readonly int _chromaticAberrationVecProperty = Shader.PropertyToID("_ChromaticAberrationVec"); + + public static int chromaticAberrationToggles = 0; + + public static bool isCaByDistort = false; + private bool _lastIsCaByDistort = false; + + public static float chromaticAberrationIntensity = 0; + public static float chromaticAberrationPos = 0; + public static float chromaticAberrationRange = 0; + + private void InitChromaticAberration() + { + // Debug.Log("InitCA"); + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_CHORATICABERRAT); + } + + private void UpdateChromaticAberration() + { + if (_lastIsCaByDistort != isCaByDistort) + { + if (isCaByDistort) + { + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_CHORATICABERRAT_BY_DISTORT); + } + else + { + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_CHORATICABERRAT_BY_DISTORT); + } + + _lastIsCaByDistort = isCaByDistort; + } + + material.SetVector(_chromaticAberrationVecProperty, + new Vector4(chromaticAberrationIntensity, chromaticAberrationPos, chromaticAberrationRange)); + chromaticAberrationIntensity = 0; //等待下一次update + chromaticAberrationPos = 0; //等待下一次update + chromaticAberrationRange = 0; //等待下一次update + } + + private void EndChromaticAberration() + { + // Debug.Log("EndCA"); + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_CHORATICABERRAT); + } + + #endregion + + #region 径向速度扭曲 + + //径向速度扭曲相关 + private readonly int _distortVecProperty = Shader.PropertyToID("_SpeedDistortVec"); + private readonly int _distortVec2Property = Shader.PropertyToID("_SpeedDistortVec2"); + private bool _lastIsDistortSpeed = false; + + public static bool isDistortScreenUVMode; + + private bool _lastIsDistortScreenUVMode; + + // [ShowInInspector] + // [LabelText("径向扭曲开关")] + // #if UNITY_EDITOR + // [BinaryInt(8)] + // #endif + public static int distortSpeedToggles; + + public static Texture2D distortTexture2D; + + public static float distortSpeedIntensity = 0; + public static float distortSpeedPosition = 0; + public static float distortSpeedRange = 0; + public static float distortSpeedMoveSpeedX = 0; + public static float distortSpeedMoveSpeedY = 0; + public static float distortTextureMidValue = 0; + + private void InitDistortSpeed() + { + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_DISTORT_SPEED); + } + + private void UpdateDistortSpeed() + { + if (_lastIsDistortScreenUVMode != isDistortScreenUVMode) + { + if (isDistortScreenUVMode) + { + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_POST_DISTORT_SCREEN_UV); + } + else + { + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_POST_DISTORT_SCREEN_UV); + } + + _lastIsDistortScreenUVMode = isDistortScreenUVMode; + } + + Vector4 distortVec = new Vector4(distortSpeedIntensity, distortSpeedPosition, distortSpeedRange, + distortTextureMidValue); + Vector4 distortVec2 = new Vector4(distortSpeedMoveSpeedX, distortSpeedMoveSpeedY, 0, 0); + material.SetVector(_distortVecProperty, distortVec); + material.SetVector(_distortVec2Property, distortVec2); + distortSpeedIntensity = 0; + distortSpeedPosition = 0; + distortSpeedRange = 0; + distortSpeedMoveSpeedX = 0; + distortSpeedMoveSpeedY = 0; + } + + private void EndDistortSpeed() + { + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_DISTORT_SPEED); + } + + #endregion + + #region 径向模糊 + + // [ShowInInspector] + // [LabelText("径向模糊开关")] + // #if UNITY_EDITOR + // [BinaryInt(8)] + // #endif + public static int radialBlurToggles = 0; + private readonly int _radialBlurVecProperty = Shader.PropertyToID("_RadialBlurVec"); + public static float radialBlurIntensity = 0; + public static float radialBlurPos = 0; + public static float radialBlurRange = 0; + public static int radialBlurSampleCount = 4; + public static bool isRadialBlurByDistort = false; + private bool _lastIsRadialBlurByDistort = false; + + private bool _lastIsRadialBlur = false; + + private void InitRadialBlur() + { + // Debug.Log("InitRB"); + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_RADIALBLUR); + } + + private void UpdateRadialBlur() + { + if (_lastIsRadialBlurByDistort != isRadialBlurByDistort) + { + if (isRadialBlurByDistort) + { + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_RADIALBLUR_BY_DISTORT); + } + else + { + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_RADIALBLUR_BY_DISTORT); + } + + _lastIsRadialBlurByDistort = isRadialBlurByDistort; + } + + Vector4 radialBlurVec = new Vector4(radialBlurIntensity * 0.1f / radialBlurSampleCount, radialBlurPos, + radialBlurRange, radialBlurSampleCount); + material.SetVector(_radialBlurVecProperty, radialBlurVec); + radialBlurIntensity = 0; + radialBlurSampleCount = 0; + radialBlurPos = 0; + radialBlurRange = 0; + } + + private void EndRadialBlur() + { + // Debug.Log("EndRB"); + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_RADIALBLUR); + } + + #endregion + + #region 震屏 + +#if CINIMACHINE_3_0 + + public static int cameraShakeToggles = 0; + + + private bool _lastIsCameraShake = false; + public static float cameraShakeIntensity = 0; + + private void UpdateCameraShake() + { + if (_perlin) + { + _perlin.AmplitudeGain = cameraShakeIntensity; + } + + cameraShakeIntensity = 0; + // #if UNITY_EDITOR + if (currentVirtualCamera) + { + CinemachineCore.SoloCamera = currentVirtualCamera; + } + // #endif + // Debug.Log(_perlin.m_AmplitudeGain); + } + + private void EndCameraShake() + { + if (_perlin) + { + _perlin.AmplitudeGain = 0; + } + + CinemachineCore.SoloCamera = null; + } +#endif + + #endregion + + #region 肌理叠加 + + //肌理图 + //注意,肌理图就是硬切,只有intensity可以做差值。 + // [ShowInInspector] + // [LabelText("肌理开关")] + // #if UNITY_EDITOR + // [BinaryInt(8)] + // #endif + public static int overlayTextureToggles = 0; + + private bool _lastIsOverlayTexture = false; + + public static float overlayTextureIntensity = 0; + + private readonly int _overlayTextureProperty = Shader.PropertyToID("_TextureOverlay"); + private readonly int _overlayTextureStProperty = Shader.PropertyToID("_TextureOverlay_ST"); + private readonly int _overlayTextureIntensityProperty = Shader.PropertyToID("_TextureOverlayIntensity"); + + private void InitOverlayTexture() + { + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_OVERLAYTEXTURE); + } + + private void UpdateOverlayTexture() + { + material.SetFloat(_overlayTextureIntensityProperty, overlayTextureIntensity); + overlayTextureIntensity = 0; + } + + private void EndOverlayTexture() + { + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_OVERLAYTEXTURE); + } + + #endregion + + #region 黑白闪 + + // [ShowInInspector] + // [LabelText("黑白闪开关")] + // #if UNITY_EDITOR + // [BinaryInt(8)] + // #endif + public static int flashToggles = 0; + + private bool _lastIsFlash = false; + + public static float flashDesaturateIntensity = 0; + public static float flashGradientRange = 0; + public static Vector4 flashTextureScaleOffset = new Vector4(1,1,0,0); + public static Vector4 flashVec = new Vector4(0, 0); + public static float flashTextureIntensity = 0.5f; + public static float flashIntensity = 1; + + public static float flashInvertIntensity = 0; + + public static float flashContrast = 0; + + public static Color flashColor = new Color(1, 1, 1, 1); + public static Color blackFlashColor = new Color(0, 0, 0, 1); + + private readonly int _flashIntensityProperty = Shader.PropertyToID("_FlashIntensity"); + private readonly int _flashDesaturateProperty = Shader.PropertyToID("_DeSaturateIntensity"); + private readonly int _flashInvertProperty = Shader.PropertyToID("_InvertIntensity"); + private readonly int _flashContrastProperty = Shader.PropertyToID("_Contrast"); + private readonly int _flashColorProperty = Shader.PropertyToID("_FlashColor"); + private readonly int _blackFlashColorProperty = Shader.PropertyToID("_BlackFlashColor"); + private readonly int _flashGradientRangeProp = Shader.PropertyToID("_FlashGradientRange"); + private readonly int _flashTextureScaleOffsetProp = Shader.PropertyToID("_FlashTexture_ST"); + private readonly int _flashVecProp = Shader.PropertyToID("_FlashVec"); + private readonly int _flashTextureIntensityProp = Shader.PropertyToID("_FlashTextureIntensity"); + + private void InitFlash() + { + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_FLASH); + } + + private void UpdateFlash() + { + material.SetFloat(_flashDesaturateProperty, flashDesaturateIntensity); + material.SetFloat(_flashInvertProperty, flashInvertIntensity); + material.SetFloat(_flashContrastProperty, flashContrast); + material.SetColor(_flashColorProperty, flashColor); + material.SetColor(_blackFlashColorProperty, blackFlashColor); + material.SetFloat(_flashGradientRangeProp, flashGradientRange); + material.SetVector(_flashTextureScaleOffsetProp, flashTextureScaleOffset); + material.SetVector(_flashVecProp, flashVec); + material.SetFloat(_flashTextureIntensityProp, flashTextureIntensity); + material.SetFloat(_flashIntensityProperty, flashIntensity); + + flashDesaturateIntensity = 0; + flashInvertIntensity = 0; + flashContrast = 0; + flashColor = Color.white; + blackFlashColor = Color.black; + flashGradientRange = 0; + flashTextureScaleOffset = Vector4.zero; + flashTextureIntensity = 0; + flashVec = Vector4.zero; + flashIntensity = 0; + } + + private void EndFlash() + { + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_FLASH); + } + + #endregion + + #region 暗角 + + // [ShowInInspector] + // [LabelText("暗角开关")] + // #if UNITY_EDITOR + // [BinaryInt(8)] + // #endif + public static int vignetteToggles = 0; + + private bool _lastIsVignette; + + public static float vignetteIntensity = 0f; + public static float vignetteRoundness = 0f; + public static float vignetteSmothness = 0f; + public static float vignetteFill = 0f; + + private readonly int _vignetteVecProperty = Shader.PropertyToID("_VignetteVec"); + + private void InitVignette() + { + flags.SetFlagBits(NBPostProcessFlags.FLAG_BIT_VIGNETTE); + } + + + private void UpdateVignette() + { + Vector4 vignetteVec = new Vector4(vignetteIntensity, vignetteRoundness, vignetteSmothness, vignetteFill); + material.SetVector(_vignetteVecProperty, vignetteVec); + vignetteIntensity = 0; + vignetteRoundness = 0; + vignetteSmothness = 0; + vignetteFill = 0; + } + + private void EndVignette() + { + flags.ClearFlagBits(NBPostProcessFlags.FLAG_BIT_VIGNETTE); + } + + + #endregion + + +#if UNITY_EDITOR + void EditorUpdate() + { + if (!Application.isPlaying) + { + LateUpdate(); //每帧Update会导致SceneView闪 + } + } + + public void ReRegistEditorUpdate() + { + EditorApplication.update -= EditorUpdate; + EditorApplication.update += EditorUpdate; + } +#endif + + } +} + + diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingManager.cs.meta b/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingManager.cs.meta new file mode 100644 index 00000000..40820cf7 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/PostProcessingManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fe30e455c04f33342bb3d1c227855682 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/RenderCameraOpaqueDistortObjectPass.cs b/Packages/NB_FX/NBPostProcessing/Runtime/RenderCameraOpaqueDistortObjectPass.cs new file mode 100644 index 00000000..2a831639 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/RenderCameraOpaqueDistortObjectPass.cs @@ -0,0 +1,100 @@ +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; +using System.Collections.Generic; +#if UNIVERSAL_RP_17_0_OR_NEWER +using UnityEngine.Rendering.RenderGraphModule; +#endif + +namespace NBShader +{ + public class RenderCameraOpaqueDistortObjectPass: ScriptableRenderPass + { + private ProfilingSampler _profilingSampler = new ProfilingSampler("RenderCameraOpaqueDistortObject"); + + private FilteringSettings _Filtering; + private readonly List _shaderTag = new List() + { + // new ShaderTagId("UniversalForward"), + // new ShaderTagId("SRPDefaultUnlit"), + // new ShaderTagId("UniversalForwardOnly") + new ShaderTagId("NBCameraOpaqueDistortPass") + }; + +#if UNIVERSAL_RP_17_0_OR_NEWER + private class RenderGraphPassData + { + public RendererListHandle rendererListHandle; + } + + private static bool IsSupportedCamera(CameraType cameraType) + { + return cameraType == CameraType.Game || cameraType == CameraType.SceneView; + } + + public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) + { + UniversalCameraData cameraData = frameData.Get(); + if (!IsSupportedCamera(cameraData.cameraType)) + return; + + UniversalResourceData resourceData = frameData.Get(); + if (!resourceData.activeColorTexture.IsValid()) + return; + + UniversalRenderingData universalRenderingData = frameData.Get(); + UniversalLightData lightData = frameData.Get(); + + using (var builder = renderGraph.AddRasterRenderPass("RenderCameraOpaqueDistortObject", out var passData)) + { + DrawingSettings drawingSettings = RenderingUtils.CreateDrawingSettings( + _shaderTag, + universalRenderingData, + cameraData, + lightData, + cameraData.defaultOpaqueSortFlags); + FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.all); + RendererListParams rendererListParameters = new RendererListParams( + universalRenderingData.cullResults, + drawingSettings, + filteringSettings); + + passData.rendererListHandle = renderGraph.CreateRendererList(rendererListParameters); + builder.UseRendererList(passData.rendererListHandle); + builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.ReadWrite); + + if (resourceData.activeDepthTexture.IsValid()) + builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.ReadWrite); + + builder.SetRenderFunc(static (RenderGraphPassData data, RasterGraphContext context) => + { + context.cmd.DrawRendererList(data.rendererListHandle); + }); + } + } +#endif + +#if !UNITY_6000_3_OR_NEWER || (URP_COMPATIBILITY_MODE && !UNITY_6000_4_OR_NEWER) +#pragma warning disable CS0618, CS0672 + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) + { + _Filtering = new FilteringSettings(RenderQueueRange.all); + } + + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + if (!(renderingData.cameraData.cameraType == CameraType.Game || renderingData.cameraData.cameraType == CameraType.SceneView)) + return; + var DisturbanceDraw = CreateDrawingSettings(_shaderTag, ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags); + CommandBuffer cmd = CommandBufferPool.Get(); + using (new ProfilingScope(cmd, _profilingSampler)) + { + context.DrawRenderers(renderingData.cullResults, ref DisturbanceDraw, ref _Filtering); + } + context.ExecuteCommandBuffer(cmd); + CommandBufferPool.Release(cmd); + } +#pragma warning restore CS0618, CS0672 +#endif + } +} diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/RenderCameraOpaqueDistortObjectPass.cs.meta b/Packages/NB_FX/NBPostProcessing/Runtime/RenderCameraOpaqueDistortObjectPass.cs.meta new file mode 100644 index 00000000..ba8e203a --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/RenderCameraOpaqueDistortObjectPass.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d9bf1337892f42c489f6d9e553271b59 +timeCreated: 1757141058 \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/ScreenColorRenderPass.cs b/Packages/NB_FX/NBPostProcessing/Runtime/ScreenColorRenderPass.cs new file mode 100644 index 00000000..ddf63f94 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/ScreenColorRenderPass.cs @@ -0,0 +1,307 @@ +#if !UNITY_6000_3_OR_NEWER || (URP_COMPATIBILITY_MODE && !UNITY_6000_4_OR_NEWER) +#define NB_URP_COMPATIBILITY_PATH +#endif + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; +using System.Reflection; +#if UNIVERSAL_RP_17_0_OR_NEWER +using UnityEngine.Rendering.RenderGraphModule; +using UnityEngine.Rendering.RenderGraphModule.Util; +#endif + +namespace NBShader +{ + public class ScreenColorRenderPass : ScriptableRenderPass + { +#if UNIVERSAL_RP_13_1_2_OR_NEWER + private RTHandle _screenColorHandle; + private RTHandle _tempRTHandle; +#else + private RenderTargetIdentifier _screenColorHandle; + private static readonly int _screenColorRTID = Shader.PropertyToID("_screenColorRT"); + private RenderTargetIdentifier _tempRTHandle = new RenderTargetIdentifier(_tempRTID); + private static readonly int _tempRTID = Shader.PropertyToID("CopyColorRT"); +#endif + private ProfilingSampler _profilingSampler; + private readonly Downsampling _downSampling; + readonly Material _material; + private static readonly int CameraTexture = Shader.PropertyToID("_CameraTexture"); + private static readonly int SampleOffset = Shader.PropertyToID("_SampleOffset"); + private static readonly int ScreenColorCopy = Shader.PropertyToID("_ScreenColorCopy1"); + + public ScreenColorRenderPass(Material material, Downsampling downSampling) + { + _material = material; + _downSampling = downSampling; +#if UNIVERSAL_RP_17_0_OR_NEWER + requiresIntermediateTexture = true; +#endif + } + + private static void DisableMipMaps(ref RenderTextureDescriptor descriptor) + { + descriptor.autoGenerateMips = false; + descriptor.useMipMap = false; + } + +#if UNIVERSAL_RP_17_0_OR_NEWER + private class GlobalTexturePassData + { + public TextureHandle texture; + public int nameID; + } + + private static bool IsSupportedCamera(CameraType cameraType) + { + return cameraType == CameraType.Game || cameraType == CameraType.SceneView; + } + + private static void SetGlobalTextureAfterPass(RenderGraph renderGraph, TextureHandle texture, int nameID, string passName) + { + using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData)) + { + passData.texture = texture; + passData.nameID = nameID; + builder.UseTexture(texture, AccessFlags.Read); + builder.AllowPassCulling(false); + builder.AllowGlobalStateModification(true); + builder.SetGlobalTextureAfterPass(texture, nameID); + builder.SetRenderFunc(static (GlobalTexturePassData data, RasterGraphContext context) => + { + }); + } + } + + private void ApplyDownsampling(ref TextureDesc descriptor) + { + switch (_downSampling) + { + case Downsampling._2xBilinear: + descriptor.width = Mathf.Max(1, descriptor.width / 2); + descriptor.height = Mathf.Max(1, descriptor.height / 2); + break; + case Downsampling._4xBilinear: + case Downsampling._4xBox: + descriptor.width = Mathf.Max(1, descriptor.width / 4); + descriptor.height = Mathf.Max(1, descriptor.height / 4); + break; + } + } + + private int GetDownsamplePassIndex() + { + return _downSampling == Downsampling._4xBox ? 1 : 0; + } + + private static void DisableMipMaps(ref TextureDesc descriptor) + { + descriptor.autoGenerateMips = false; + descriptor.useMipMap = false; + } + + public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) + { + UniversalCameraData cameraData = frameData.Get(); + if (!IsSupportedCamera(cameraData.cameraType) || _material == null) + return; + + UniversalResourceData resourceData = frameData.Get(); + TextureHandle source = resourceData.activeColorTexture; + if (!source.IsValid()) + return; + + TextureDesc descriptor = renderGraph.GetTextureDesc(source); + descriptor.name = "CopyColorRT"; + descriptor.clearBuffer = false; + descriptor.depthBufferBits = DepthBits.None; + DisableMipMaps(ref descriptor); + ApplyDownsampling(ref descriptor); + + TextureHandle destination = renderGraph.CreateTexture(descriptor); + + if (_downSampling == Downsampling._4xBox) + _material.SetFloat(SampleOffset, 2); + + RenderGraphUtils.BlitMaterialParameters blitParameters = + new RenderGraphUtils.BlitMaterialParameters(source, destination, _material, GetDownsamplePassIndex()); + blitParameters.sourceTexturePropertyID = CameraTexture; + + renderGraph.AddBlitPass(blitParameters, "ScreenColorRender"); + SetGlobalTextureAfterPass(renderGraph, destination, ScreenColorCopy, "Set Screen Color Copy"); + } +#endif + + +#if UNIVERSAL_RP_13_1_2_OR_NEWER +#if NB_URP_COMPATIBILITY_PATH +#pragma warning disable CS0618, CS0672 + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) + { + ConfigureTarget(_screenColorHandle); + + } +#pragma warning restore CS0618, CS0672 +#endif + + public void SetUp(RTHandle colorHandle) + { +#if NB_URP_COMPATIBILITY_PATH +#pragma warning disable CS0618 + _profilingSampler ??= new ProfilingSampler("ScreenColorRender"); + _screenColorHandle = colorHandle; + RenderTextureDescriptor descriptor = _screenColorHandle.rt.descriptor; + DisableMipMaps(ref descriptor); + switch (_downSampling) + { + case Downsampling._2xBilinear: + descriptor.width /= 2; + descriptor.height /= 2; + break; + case Downsampling._4xBilinear: + descriptor.width /= 4; + descriptor.height /= 4; + break; + case Downsampling._4xBox: + descriptor.width /= 4; + descriptor.height /= 4; + break; + } + RenderingUtils.ReAllocateIfNeeded(ref _tempRTHandle, descriptor,name:"CopyColorRT"); +#pragma warning restore CS0618 +#endif + } + + +#else +#if NB_URP_COMPATIBILITY_PATH + + FieldInfo cameraColorAttachment = typeof(UniversalRenderer).GetField("m_ActiveCameraColorAttachment", BindingFlags.NonPublic|BindingFlags.Instance); + +#pragma warning disable CS0618, CS0672 + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) + { + + var renderer = (UniversalRenderer)renderingData.cameraData.renderer; + + // cmd.SetGlobalTexture(_screenColorRTID,_screenColorHandle); + SetUpCopyColorRT(renderer,renderingData.cameraData.cameraTargetDescriptor,cmd); + ConfigureTarget(_tempRTHandle); + ConfigureClear(ClearFlag.Color, Color.clear); + } + + public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) + { + } +#pragma warning restore CS0618, CS0672 + + public void SetUp(ScriptableRenderer renderer) + { + RenderTargetHandle value = (RenderTargetHandle)cameraColorAttachment.GetValue(renderer); + _screenColorHandle = value.Identifier(); + // _screenColorHandle = colorTarget; + } + + public void SetUpCopyColorRT(ScriptableRenderer renderer,RenderTextureDescriptor descriptor ,CommandBuffer cmd) + { + DisableMipMaps(ref descriptor); + switch (_downSampling) + { + case Downsampling._2xBilinear: + descriptor.width /= 2; + descriptor.height /= 2; + break; + case Downsampling._4xBilinear: + descriptor.width /= 4; + descriptor.height /= 4; + break; + case Downsampling._4xBox: + descriptor.width /= 4; + descriptor.height /= 4; + break; + } + cmd.GetTemporaryRT( _tempRTID, descriptor,FilterMode.Bilinear); + } + + public override void OnCameraCleanup(CommandBuffer cmd) + { + cmd.ReleaseTemporaryRT(_tempRTID); + } +#endif +#endif + +#if NB_URP_COMPATIBILITY_PATH +#pragma warning disable CS0618, CS0672 + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + if (!(renderingData.cameraData.cameraType == CameraType.Game || renderingData.cameraData.cameraType == CameraType.SceneView)) + return; + if (_material == null) + return; + CommandBuffer cmd = CommandBufferPool.Get(); + + using (new ProfilingScope(cmd, _profilingSampler)) + { +#if UNIVERSAL_RP_13_1_2_OR_NEWER + + _material.SetTexture(CameraTexture, _screenColorHandle); + cmd.SetRenderTarget((RenderTargetIdentifier)_tempRTHandle); + switch (_downSampling) + { + case Downsampling._2xBilinear: + + Blitter.BlitTexture(cmd, _screenColorHandle, Vector2.one, _material, 0); + break; + case Downsampling._4xBilinear: + Blitter.BlitTexture(cmd, _screenColorHandle, Vector2.one, _material, 0); + break; + case Downsampling._4xBox: + _material.SetFloat(SampleOffset,2); + Blitter.BlitTexture(cmd, _screenColorHandle, Vector2.one, _material, 1); + break; + default: + Blitter.BlitTexture(cmd, _screenColorHandle, Vector2.one, _material, 0); + break; + } +#else + cmd.SetGlobalTexture(_screenColorRTID,_screenColorHandle); + + _material.SetTexture(CameraTexture,Shader.GetGlobalTexture(_screenColorRTID)); + cmd.SetRenderTarget(_tempRTHandle); + switch (_downSampling) + { + case Downsampling._2xBilinear: + cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _material, 0,0); + break; + case Downsampling._4xBilinear: + cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _material, 0,0); + break; + case Downsampling._4xBox: + _material.SetFloat(SampleOffset,2); + cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _material, 0,1); + break; + default: + cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _material, 0,0); + break; + } + +#endif + cmd.SetGlobalTexture(ScreenColorCopy, _tempRTHandle); + } + + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + CommandBufferPool.Release(cmd); + } +#pragma warning restore CS0618, CS0672 +#endif + + public void Dispose() + { + #if UNIVERSAL_RP_13_1_2_OR_NEWER && NB_URP_COMPATIBILITY_PATH + _tempRTHandle?.Release(); + #endif + } + } +} diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/ScreenColorRenderPass.cs.meta b/Packages/NB_FX/NBPostProcessing/Runtime/ScreenColorRenderPass.cs.meta new file mode 100644 index 00000000..ef85a01b --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/ScreenColorRenderPass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ff8358dc3f3531d4c92a43a49d07f36c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/com.xuanxuan.nb.postprocessing.asmdef b/Packages/NB_FX/NBPostProcessing/Runtime/com.xuanxuan.nb.postprocessing.asmdef new file mode 100644 index 00000000..af4df172 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/com.xuanxuan.nb.postprocessing.asmdef @@ -0,0 +1,35 @@ +{ + "name": "com.xuanxuan.nb.postprocessing", + "rootNamespace": "", + "references": [ + "GUID:df380645f10b7bc4b97d4f5eb6303d95", + "GUID:15fc0a57446b3144c949da3e2b9737a9", + "GUID:4307f53044263cf4b835bd812fc161a4", + "GUID:8f9e4d586616f13449cfeb86c5f704c2" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.cinemachine", + "expression": "3.0", + "define": "CINIMACHINE_3_0" + }, + { + "name": "com.unity.render-pipelines.universal", + "expression": "13.1.2", + "define": "UNIVERSAL_RP_13_1_2_OR_NEWER" + }, + { + "name": "com.unity.render-pipelines.universal", + "expression": "17.0.0", + "define": "UNIVERSAL_RP_17_0_OR_NEWER" + } + ], + "noEngineReferences": false +} diff --git a/Packages/NB_FX/NBPostProcessing/Runtime/com.xuanxuan.nb.postprocessing.asmdef.meta b/Packages/NB_FX/NBPostProcessing/Runtime/com.xuanxuan.nb.postprocessing.asmdef.meta new file mode 100644 index 00000000..0cc23c51 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Runtime/com.xuanxuan.nb.postprocessing.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a1f23b61b189bd949adfd0f7a353734f +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Shader.meta b/Packages/NB_FX/NBPostProcessing/Shader.meta new file mode 100644 index 00000000..67b64f3f --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b96c6f78e9ea0924b92677f2c4812124 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Shader/ColorBlit.shader b/Packages/NB_FX/NBPostProcessing/Shader/ColorBlit.shader new file mode 100644 index 00000000..78a0f8f0 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/ColorBlit.shader @@ -0,0 +1,238 @@ +Shader "XuanXuan/ColorBlit" +{ + HLSLINCLUDE + #pragma target 2.0 + #pragma editor_sync_compilation + #pragma multi_compile _ DISABLE_TEXTURE2D_X_ARRAY + #pragma multi_compile _ BLIT_SINGLE_SLICE + // Core.hlsl for XR dependencies + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" + ENDHLSL + + SubShader + { + Tags + { + "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline" + } + ZWrite Off Cull Off + Pass + { + Name "ColorBlitPass0" + + HLSLPROGRAM + #pragma vertex vert + // #pragma vertex vert + // #pragma fragment FragNearest + #pragma fragment frag + #pragma enable_d3d11_debug_symbols + + Texture2D _CameraTexture; + // Texture2D _CameraTexture; + // + // struct MyAttributes + // { + // float4 positionOS : POSITION; + // float4 texCoord : TEXCOORD0; + // }; + + // + // Varyings vert(MyAttributes IN) + // { + // Varyings OUT = (Varyings)0; + // OUT.positionCS = float4(IN.positionOS.xyz,1); + // half4 clipVertex = OUT.positionCS/OUT.positionCS.w; + // OUT.texcoord = ComputeScreenPos(clipVertex); + // return OUT; + // } + + Varyings vert(Attributes input)//避开官方_BlitScaleBias为0的错误。 + { + Varyings output; + UNITY_SETUP_INSTANCE_ID(input); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + #if SHADER_API_GLES + float4 pos = input.positionOS; + float2 uv = input.uv; + #else + float4 pos = GetFullScreenTriangleVertexPosition(input.vertexID); + float2 uv = GetFullScreenTriangleTexCoord(input.vertexID); + #endif + + output.positionCS = pos; + // output.texcoord = uv * _BlitScaleBias.xy + _BlitScaleBias.zw; + output.texcoord = uv; + return output; + } + + half4 frag (Varyings input) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + + float4 color = SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_LinearRepeat, input.texcoord); + + return color; + } + ENDHLSL + } + Pass + { + Name "BoxDownsample" + + ZWrite Off + Cull Off + + HLSLPROGRAM + // #pragma vertex Vert + #pragma vertex vert + #pragma fragment FragBoxDownsample + #pragma enable_d3d11_debug_symbols + + + Texture2D _CameraTexture; + SAMPLER(sampler_CameraTexture); + + #if UNITY_VERSION < 202320 + float4 _BlitTexture_TexelSize; + #endif + + Varyings vert(Attributes input)//避开官方_BlitScaleBias为0的错误。 + { + Varyings output; + UNITY_SETUP_INSTANCE_ID(input); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + #if SHADER_API_GLES + float4 pos = input.positionOS; + float2 uv = input.uv; + #else + float4 pos = GetFullScreenTriangleVertexPosition(input.vertexID); + float2 uv = GetFullScreenTriangleTexCoord(input.vertexID); + #endif + + output.positionCS = pos; + // output.texcoord = uv * _BlitScaleBias.xy + _BlitScaleBias.zw; + output.texcoord = uv; + return output; + } + + float _SampleOffset; + + half4 FragBoxDownsample(Varyings input) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + + float2 uv = UnityStereoTransformScreenSpaceTex(input.texcoord); + float4 d = _BlitTexture_TexelSize.xyxy * float4(-_SampleOffset, -_SampleOffset, _SampleOffset, + _SampleOffset); + + half4 s; + + s = SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_CameraTexture, uv + d.xy); + s += SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_CameraTexture, uv + d.zy); + s += SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_CameraTexture, uv + d.xw); + s += SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_CameraTexture, uv + d.zw); + + return s * 0.25h; + } + ENDHLSL + } + Pass + { + Name "ColorBlitPass_URP_13_1_2_OR_OLDER" + + HLSLPROGRAM + #pragma vertex vert + // #pragma vertex vert + // #pragma fragment FragNearest + #pragma fragment frag + #pragma enable_d3d11_debug_symbols + + Texture2D _CameraTexture; + // Texture2D _CameraTexture; + + struct MyAttributes + { + float4 positionOS : POSITION; + float4 texCoord : TEXCOORD0; + }; + + + Varyings vert(MyAttributes IN) + { + Varyings OUT = (Varyings)0; + OUT.positionCS = float4(IN.positionOS.xyz,1); + half4 clipVertex = OUT.positionCS/OUT.positionCS.w; + OUT.texcoord = ComputeScreenPos(clipVertex); + return OUT; + } + half4 frag (Varyings input) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + + float4 color = SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_LinearRepeat, input.texcoord); + + return color; + } + ENDHLSL + } + Pass + { + Name "BoxDownsample_URP_13_1_2_OR_OLDER" + + ZWrite Off + Cull Off + + HLSLPROGRAM + #pragma vertex vert + #pragma fragment FragBoxDownsample + #pragma enable_d3d11_debug_symbols + + + Texture2D _CameraTexture; + SAMPLER(sampler_CameraTexture); + + #if UNITY_VERSION < 202320 + float4 _BlitTexture_TexelSize; + #endif + + + float _SampleOffset; + struct MyAttributes + { + float4 positionOS : POSITION; + float4 texCoord : TEXCOORD0; + }; + + Varyings vert(MyAttributes IN) + { + Varyings OUT = (Varyings)0; + OUT.positionCS = float4(IN.positionOS.xyz,1); + half4 clipVertex = OUT.positionCS/OUT.positionCS.w; + OUT.texcoord = ComputeScreenPos(clipVertex); + return OUT; + } + + half4 FragBoxDownsample(Varyings input) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + + float2 uv = UnityStereoTransformScreenSpaceTex(input.texcoord); + float4 d = _BlitTexture_TexelSize.xyxy * float4(-_SampleOffset, -_SampleOffset, _SampleOffset, + _SampleOffset); + + half4 s; + + s = SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_CameraTexture, uv + d.xy); + s += SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_CameraTexture, uv + d.zy); + s += SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_CameraTexture, uv + d.xw); + s += SAMPLE_TEXTURE2D_X(_CameraTexture, sampler_CameraTexture, uv + d.zw); + + return s * 0.25h; + } + ENDHLSL + } + } +} \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Shader/ColorBlit.shader.meta b/Packages/NB_FX/NBPostProcessing/Shader/ColorBlit.shader.meta new file mode 100644 index 00000000..2da1d64c --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/ColorBlit.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3e92fe624a4f13d4eadc7753e236006a +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Shader/ColorBufferBlit.shader b/Packages/NB_FX/NBPostProcessing/Shader/ColorBufferBlit.shader new file mode 100644 index 00000000..8642524a --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/ColorBufferBlit.shader @@ -0,0 +1,105 @@ +Shader "XuanXuan/ColorBufferBlit" +{ + HLSLINCLUDE + #pragma target 2.0 + #pragma editor_sync_compilation + #pragma multi_compile _ DISABLE_TEXTURE2D_X_ARRAY + #pragma multi_compile _ BLIT_SINGLE_SLICE + // Core.hlsl for XR dependencies + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" + ENDHLSL + + SubShader + { + Tags + { + "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline" + } + ZWrite Off Cull Off + Pass + { + Name "ColorBlitPass0" + + HLSLPROGRAM + // #pragma vertex Vert + #pragma vertex vert + // #pragma fragment FragNearest + #pragma fragment frag + #pragma enable_d3d11_debug_symbols + + + Texture2D _CameraColorTexture; + SAMPLER(sampler_CameraColorTexture); + + struct MyAttributes + { + float4 positionOS : POSITION; + float4 texCoord : TEXCOORD0; + }; + + + Varyings vert(MyAttributes IN) + { + Varyings OUT = (Varyings)0; + OUT.positionCS = float4(IN.positionOS.xyz,1); + half4 clipVertex = OUT.positionCS/OUT.positionCS.w; + OUT.texcoord = ComputeScreenPos(clipVertex); + return OUT; + } + half4 frag (Varyings input) : SV_Target + { + // UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + float4 color = SAMPLE_TEXTURE2D_X(_CameraColorTexture, sampler_LinearRepeat, input.texcoord); + + + return color; + } + ENDHLSL + } + Pass + { + Name "BoxDownsample" + + ZWrite Off + Cull Off + + HLSLPROGRAM + #pragma vertex Vert + #pragma fragment FragBoxDownsample + #pragma enable_d3d11_debug_symbols + + + // Texture2D _CameraTexture; + // SAMPLER(sampler_CameraTexture); + Texture2D _CameraColorTexture; + SAMPLER(sampler_CameraColorTexture); + + #if UNITY_VERSION < 202320 + float4 _BlitTexture_TexelSize; + #endif + + + float _SampleOffset; + + half4 FragBoxDownsample(Varyings input) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + + float2 uv = UnityStereoTransformScreenSpaceTex(input.texcoord); + float4 d = _BlitTexture_TexelSize.xyxy * float4(-_SampleOffset, -_SampleOffset, _SampleOffset, + _SampleOffset); + + half4 s; + + s = SAMPLE_TEXTURE2D_X(_CameraColorTexture, sampler_CameraColorTexture, uv + d.xy); + s += SAMPLE_TEXTURE2D_X(_CameraColorTexture, sampler_CameraColorTexture, uv + d.zy); + s += SAMPLE_TEXTURE2D_X(_CameraColorTexture, sampler_CameraColorTexture, uv + d.xw); + s += SAMPLE_TEXTURE2D_X(_CameraColorTexture, sampler_CameraColorTexture, uv + d.zw); + + return s * 0.25h; + } + ENDHLSL + } + } +} \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Shader/ColorBufferBlit.shader.meta b/Packages/NB_FX/NBPostProcessing/Shader/ColorBufferBlit.shader.meta new file mode 100644 index 00000000..9e84e657 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/ColorBufferBlit.shader.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3150dab783854cd6b791d5db3be4a966 +timeCreated: 1747582276 \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Shader/DistortSpeedNoise.png b/Packages/NB_FX/NBPostProcessing/Shader/DistortSpeedNoise.png new file mode 100644 index 00000000..6f745d16 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/DistortSpeedNoise.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15fb002511f6feb08bfd05287edb4a3c8525cec24fc16a6eb2c192e7456e1aee +size 19230 diff --git a/Packages/NB_FX/NBPostProcessing/Shader/DistortSpeedNoise.png.meta b/Packages/NB_FX/NBPostProcessing/Shader/DistortSpeedNoise.png.meta new file mode 100644 index 00000000..6cb127ae --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/DistortSpeedNoise.png.meta @@ -0,0 +1,156 @@ +fileFormatVersion: 2 +guid: 7f808d0c8608b954d8f20cb4132c3049 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: iOS + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Shader/Disturbance.shader b/Packages/NB_FX/NBPostProcessing/Shader/Disturbance.shader new file mode 100644 index 00000000..bca5c29a --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/Disturbance.shader @@ -0,0 +1,113 @@ +Shader "XuanXuan/Disturbance" +{ + Properties + { + [MhGroup(Main)]_mainTex("Main", float) = 0 + [MhTexture(Main)] _MaskMap("Mask Map", 2D) = "white" {} + + [MhTexture(Main,_Strength,on)]_NoiseMap("Noise Map", 2D) = "white"{} + [HideInInspector]_Strength("Strength", Range(-0.2,0.2)) =0.1 + [MhToggleKeyword(Main,_PARTICLE_CUSTOMDATA_ON)]_ParticleCustomDataOn("Particle customData Strength", float) = 0 + [HideInInspector]_SurfaceType("surfaceType",float)=1 + [HideInInspector] _QueueOffset("Queue offset", Float) = 0.0 + } + + // The SubShader block containing the Shader code. + SubShader + { + // SubShader Tags define when and under which conditions a SubShader block or + // a pass is executed. + Tags + { + "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" "Queue" = "Transparent" "IgnoreProjector" = "True" + } + + Pass + { + Blend SrcAlpha OneMinusSrcAlpha + //ZTest Always + Cull Off + HLSLPROGRAM + //gpuInstancing on + #pragma multi_compile_instancing + #pragma instancing_options renderinglayer + #pragma multi_compile _ DOTS_INSTANCING_ON + #pragma target 3.5 DOTS_INSTANCING_ON + + #pragma shader_feature_local_fragment _PARTICLE_CUSTOMDATA_ON + #pragma enable_d3d11_debug_symbols + + + // This line defines the name of the vertex shader. + #pragma vertex vert + // This line defines the name of the fragment shader. + #pragma fragment frag + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" + + + // This example uses the Attributes structure as an input structure in + // the vertex shader. + struct Attributes + { + float4 positionOS : POSITION; + float4 uv : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct Varyings + { + // The positions in this struct must have the SV_POSITION semantic. + float4 positionHCS : SV_POSITION; + float4 uv :TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + Texture2D _NoiseMap; + SAMPLER(sampler_NoiseMap); + + Texture2D _MaskMap; + SAMPLER(sampler_MaskMap); + float _Strength; + + CBUFFER_START(UnityPerMaterial) + + float4 _NoiseMap_ST; + + CBUFFER_END + + + Varyings vert(Attributes IN) + { + Varyings OUT; + // Declaring the output object (OUT) with the Varyings struct. + + UNITY_SETUP_INSTANCE_ID(IN); + UNITY_TRANSFER_INSTANCE_ID(IN, OUT); + + OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); + OUT.uv = IN.uv; + return OUT; + } + + half4 frag(Varyings IN) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(IN); + + half2 screenSpaceUV = IN.positionHCS.xy / _ScaledScreenParams.xy; + const half2 noiseUV = screenSpaceUV * _NoiseMap_ST.xy + _NoiseMap_ST.zw; + + half noise = SAMPLE_TEXTURE2D(_NoiseMap, sampler_NoiseMap, noiseUV).r * 2 - 1; + half mask = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, IN.uv.xy).r; + noise = lerp(0, noise, mask); + + //noise = (noise * _Strength * 5) * 0.5 + 0.5; + noise = (noise * _Strength) * 1.25 + 0.5; + + return half4(noise.xxx, 1.0); + } + ENDHLSL + } + } + customEditor "ShaderEditor.MhBaseShaderGUI" +} \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Shader/Disturbance.shader.meta b/Packages/NB_FX/NBPostProcessing/Shader/Disturbance.shader.meta new file mode 100644 index 00000000..ebf3b63b --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/Disturbance.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1b530af6d4d97eb4c8f3725d4cd3e9b8 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Shader/FullScreenDisturbance.shader b/Packages/NB_FX/NBPostProcessing/Shader/FullScreenDisturbance.shader new file mode 100644 index 00000000..43aa7062 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/FullScreenDisturbance.shader @@ -0,0 +1,84 @@ +Shader "XuanXuan/FullScreenDisturbance" +{ + Properties + { + _Strength("Strength", Range(-0.2,0.2)) =0 + _BaseMap("Base Map", 2D) = "white" + //_Mask("Mask", 2D) = "white" + + } + + // The SubShader block containing the Shader code. + SubShader + { + // SubShader Tags define when and under which conditions a SubShader block or + // a pass is executed. + Tags + { + "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" + } + + Pass + { + + stencil + { + Ref 1 + Comp equal + Pass keep + } + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // This line defines the name of the vertex shader. + #pragma vertex vert + // This line defines the name of the fragment shader. + #pragma fragment frag + + Texture2D _BlitTexture; + SAMPLER(sampler_BlitTexture); + Texture2D _BaseMap; + SAMPLER(sampler_BaseMap); + Texture2D _Mask; + SAMPLER(simpler_Mask); + float _Strength; + + struct Attributes + { + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : INSTANCEID_SEMANTIC; + #endif + uint vertexID : VERTEXID_SEMANTIC; + }; + + struct Varyings + { + float4 position : SV_POSITION; + float2 uv : TEXCOORD0; + #if UNITY_ANY_INSTANCING_ENABLED + uint instanceID : CUSTOM_INSTANCE_ID; + #endif + }; + + + Varyings vert(Attributes input) + { + Varyings output; + output.position = GetFullScreenTriangleVertexPosition(input.vertexID, UNITY_NEAR_CLIP_VALUE); + output.uv = output.position.xy * 0.5 + 0.5; + return output; + } + + float4 frag(Varyings packedInput):SV_TARGET + { + float2 baseUV = packedInput.position / _ScreenParams.xy; + float3 noise = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, baseUV); + noise=lerp(0,noise,noise.b); + baseUV += noise.xy * _Strength; + return SAMPLE_TEXTURE2D(_BlitTexture, sampler_BlitTexture, baseUV); + } + ENDHLSL + } + } + +} \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Shader/FullScreenDisturbance.shader.meta b/Packages/NB_FX/NBPostProcessing/Shader/FullScreenDisturbance.shader.meta new file mode 100644 index 00000000..26011dd2 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/FullScreenDisturbance.shader.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 126dad763ce350945945655d5c062248 +ShaderImporter: + externalObjects: {} + defaultTextures: + - _BaseMap: {instanceID: 0} + - _Mask: {instanceID: 0} + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Shader/HLSL.meta b/Packages/NB_FX/NBPostProcessing/Shader/HLSL.meta new file mode 100644 index 00000000..bbfc38db --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/HLSL.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e73bff430617bbc44ae5b87fb0fa9abf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Shader/HLSL/PostProcessingFlags.hlsl b/Packages/NB_FX/NBPostProcessing/Shader/HLSL/PostProcessingFlags.hlsl new file mode 100644 index 00000000..5310a0d6 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/HLSL/PostProcessingFlags.hlsl @@ -0,0 +1,29 @@ +#ifndef POST_PROCESSING_FLAGS +#define POST_PROCESSING_FLAGS + + +#if defined(CUSTOM_POSTPROCESS) + uint _NBPostProcessFlags; + #define FLAG_BIT_NB_POSTPROCESS_ON (1 << 0) + #define FLAG_BIT_DISTORT_SPEED (1 << 1) + #define FLAG_BIT_OVERLAYTEXTURE (1 << 2) + #define FLAG_BIT_FLASH (1 << 3) + #define FLAG_BIT_CHORATICABERRAT (1 << 4) + #define FLAG_BIT_RADIALBLUR (1 << 5) + #define FLAG_BIT_VIGNETTE (1 << 6) + #define FLAG_BIT_OVERLAYTEXTURE_POLLARCOORD (1 << 7) + #define FLAG_BIT_OVERLAYTEXTURE_MASKMAP (1 << 8) + #define FLAG_BIT_POST_DISTORT_SCREEN_UV (1 << 9) + #define FLAG_BIT_RADIALBLUR_BY_DISTORT (1 << 10) + #define FLAG_BIT_CHORATICABERRAT_BY_DISTORT (1 << 11) + #define FLAG_BIT_FLASHTEXTURE_POLLARCOORD (1 << 12) + + + + bool CheckLocalFlags(uint bits) + { + return (_NBPostProcessFlags&bits) != 0; + } +#endif + +#endif \ No newline at end of file diff --git a/Packages/NB_FX/NBPostProcessing/Shader/HLSL/PostProcessingFlags.hlsl.meta b/Packages/NB_FX/NBPostProcessing/Shader/HLSL/PostProcessingFlags.hlsl.meta new file mode 100644 index 00000000..6a154330 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/HLSL/PostProcessingFlags.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8d59b331ef0707e49a98c91244bd0c1a +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBPostProcessing/Shader/NBPostProcessUber.shader b/Packages/NB_FX/NBPostProcessing/Shader/NBPostProcessUber.shader new file mode 100644 index 00000000..c80cd5f7 --- /dev/null +++ b/Packages/NB_FX/NBPostProcessing/Shader/NBPostProcessUber.shader @@ -0,0 +1,442 @@ +Shader "XuanXuan/Postprocess/NBPostProcessUber" +{ + Properties + { +// [MainTexture] _BaseMap("Base Map", 2D) = "white" + _SpeedDistortMap("速度径向扭曲贴图", 2D) = "white" + _SpeedDistortVec("速度径向 x强度y位置z范围w速度",Vector) = (0,0,0,0) + _SpeedDistortVec2("速度径向 x:uvX速度 y:uvY速度",Vector) = (0,0,0,0) + + _TextureOverlay("肌理附加图",2D) = "white" + _TextureOverlayIntensity("肌理附加强度",Float) = 0 + _TextureOverlayAnim("机理图动画",Vector) = (0,0,0,0) + _TextureOverlayMask("肌理图蒙板",2D) = "white" + + _InvertIntensity("反向强度",Float) = 0 + _DeSaturateIntensity("饱和度强度",Float) = 0 + _Contrast("对比度",Float) = 1 + _FlashIntensity("反闪效果强度",Float) = 1 + _FlashColor("闪颜色", Vector) = (1, 1, 1, 1) + _BlackFlashColor("闪黑颜色", Vector) = (0, 0, 0, 1) + _FlashTexture("黑白闪细节图",2D) = "white" + _FlashTextureIntensity("黑白细节图混合强度",Float) = 0.5 + _FlashGradientRange("黑白闪过渡范围",Float) = 1 + _FlashVec("xy:FlashTextureOffsetAnim",Vector) = (0,0,0,0) + + + [HideInInspector] _NBPostProcessFlags("_NBPostProcessFlags", Integer) = 0 + _ChromaticAberrationVector("色散矢量",Vector) = (1,0,0,0) + + _CustomScreenCenter("自定义屏幕中心",Vector) = (0.5,0.5,0,0) + _RadialBlurVec("径向模糊矢量 x强度",Vector) = (1,0,0,0) + _VignetteVec("暗角矢量 x强度,y圆度,z光滑度",Vector) = (1,0,0,0) + + + //不知道为什么,这里写成Color老是出错。 + _VignetteColor("暗角颜色",Vector) = (0.0,0.0,0.0,1.0) + + } + + // The SubShader block containing the Shader code. + SubShader + { + // SubShader Tags define when and under which conditions a SubShader block or + // a pass is executed. + Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" } + + Pass + { + Cull Off + Blend SrcAlpha OneMinusSrcAlpha + ZTest Off + HLSLPROGRAM + // This line defines the name of the vertex shader. + #pragma vertex vert + // This line defines the name of the fragment shader. + #pragma fragment frag + #define CUSTOM_POSTPROCESS + // #define _POLARCOORDINATES + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" + + #include "HLSL/PostProcessingFlags.hlsl" + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + + + // This example uses the Attributes structure as an input structure in + // the vertex shader. + + + struct Attributes + { + float4 positionOS : POSITION; + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct Varyings + { + // The positions in this struct must have the SV_POSITION semantic. + float4 positionHCS : SV_POSITION; + half2 uv :TEXCOORD0; + UNITY_VERTEX_OUTPUT_STEREO + }; + + TEXTURE2D_X(_ScreenColorCopy1); + SAMPLER(_linear_clamp); + SAMPLER(sampler_ScreenColorCopy1); + + TEXTURE2D(_DisturbanceMaskTex); + SAMPLER(sampler_DisturbanceMaskTex); + + Texture2D _SpeedDistortMap; + SAMPLER(sampler_SpeedDistortMap); + + TEXTURE2D(_TextureOverlay); + SAMPLER(sampler_TextureOverlay); + TEXTURE2D(_TextureOverlayMask); + SAMPLER(sampler_TextureOverlayMask); + + TEXTURE2D(_FlashTexture); + SAMPLER(sampler_FlashTexture); + + #if UNITY_VERSION < 202220 + SAMPLER(sampler_LinearClamp); + #endif + + CBUFFER_START(UnityPerMaterial) + + float4 _SpeedDistortMap_ST; + half4 _SpeedDistortVec; + float4 _SpeedDistortVec2; + + half4 _TextureOverlay_ST; + half _TextureOverlayIntensity; + half4 _TextureOverlayMask_ST; + half4 _TextureOverlayAnim; + + half _FlashIntensity; + half _InvertIntensity; + half _DeSaturateIntensity; + half _Contrast; + half _FlashGradientRange; + half _FlashTextureIntensity; + float4 _FlashTexture_ST; + float4 _FlashVec; + half3 _FlashColor; + half3 _BlackFlashColor; + + half4 _ChromaticAberrationVec; + half4 _CustomScreenCenter; + half4 _RadialBlurVec; + half4 _VignetteVec; + half4 _VignetteColor; + + CBUFFER_END + + half4 SAMPLE_TEXTURE2D_CHORATICABERRAT(half2 screenUV,half2 distortUV,half2 blurVec,half distToCenter) + { + if(CheckLocalFlags(FLAG_BIT_CHORATICABERRAT_BY_DISTORT)) + { + blurVec = blurVec*0.25*_ChromaticAberrationVec.x; + } + else + { + half intensity = 1; + half range = _ChromaticAberrationVec.z*0.5f; + intensity = NB_Remap(distToCenter,_ChromaticAberrationVec.y-range,_ChromaticAberrationVec.y+range,0,1); + blurVec = blurVec*0.25*_ChromaticAberrationVec.x*intensity; + } + half r = SAMPLE_TEXTURE2D_X(_ScreenColorCopy1, sampler_LinearClamp, screenUV + distortUV ).x; + half g = SAMPLE_TEXTURE2D_X(_ScreenColorCopy1, sampler_LinearClamp, blurVec + screenUV + distortUV ).y; + half b = SAMPLE_TEXTURE2D_X(_ScreenColorCopy1, sampler_LinearClamp, blurVec * 2.0 + screenUV + distortUV).z; + + half a = dot(blurVec,blurVec)*100000; + return half4(r,g,b,a); + } + + + + Varyings vert(Attributes IN) + { + // Declaring the output object (OUT) with the Varyings struct. + Varyings OUT; + UNITY_SETUP_INSTANCE_ID(IN); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); + + OUT.positionHCS = float4(IN.positionOS.xyz, 1.0); + half4 clipVertex = OUT.positionHCS/OUT.positionHCS.w; + OUT.uv = ComputeScreenPos(clipVertex); + // Returning the output. + return OUT; + } + + half4 frag(Varyings IN) : SV_Target + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN); + + half2 screenUV = IN.uv; + half2 distortUV = 0; + half2 distortUVWithoutIntensity=0; + + half4 color = 0; + + half2 polarCoordinates = 0; + + //half disturbanceMask = (SAMPLE_TEXTURE2D(_DisturbanceMaskTex, _linear_clamp, screenUV)) * 2 - 1 + 0.00392; //8位0.5校准 + //disturbanceMask *= 0.4; + //half2 disturbanceMask = (SAMPLE_TEXTURE2D(_DisturbanceMaskTex, _linear_clamp, screenUV).xy) * 0.8 - 0.398432; //上面两行合并 + + half2 disturbanceMask = (SAMPLE_TEXTURE2D(_DisturbanceMaskTex, _linear_clamp, screenUV).xy); + // return half4(disturbanceMask,0,1);//上面两行合并 + + + color.a = SimpleSmoothstep(0,0.01,abs(disturbanceMask.x + disturbanceMask.y)); + screenUV += disturbanceMask; + + UNITY_BRANCH + if (!CheckLocalFlags(FLAG_BIT_NB_POSTPROCESS_ON)) + { + color.rgb = SAMPLE_TEXTURE2D_X(_ScreenColorCopy1, sampler_LinearClamp, screenUV).rgb; + } + + UNITY_BRANCH + if((CheckLocalFlags(FLAG_BIT_DISTORT_SPEED)& (!CheckLocalFlags(FLAG_BIT_POST_DISTORT_SCREEN_UV)))|CheckLocalFlags(FLAG_BIT_OVERLAYTEXTURE_POLLARCOORD)|CheckLocalFlags(FLAG_BIT_FLASHTEXTURE_POLLARCOORD)|CheckLocalFlags(FLAG_BIT_FLASH)) + { + polarCoordinates= PolarCoordinates(screenUV,_CustomScreenCenter.xy); + } + + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_DISTORT_SPEED)) + { + _SpeedDistortMap_ST.zw += _SpeedDistortVec2.xy * _Time.y; + // return half4(polarCoordinates,0,1); + half2 distortSpeedUV; + if(CheckLocalFlags(FLAG_BIT_POST_DISTORT_SCREEN_UV)) + { + distortSpeedUV = screenUV* _SpeedDistortMap_ST.xy+_SpeedDistortMap_ST.zw; + half2 noise = SAMPLE_TEXTURE2D(_SpeedDistortMap,sampler_SpeedDistortMap,distortSpeedUV); + noise = noise * 2-1+_SpeedDistortVec.w*0.1; + half distortStrength = _SpeedDistortVec.x * 0.2; + distortUVWithoutIntensity = noise; + distortUV = noise * distortStrength; + + } + else + { + distortSpeedUV = polarCoordinates * _SpeedDistortMap_ST.xy + _SpeedDistortMap_ST.zw; + half noise = SAMPLE_TEXTURE2D(_SpeedDistortMap,sampler_SpeedDistortMap,distortSpeedUV); + noise *= SimpleSmoothstep(_SpeedDistortVec.y,_SpeedDistortVec.y+_SpeedDistortVec.z,(distortSpeedUV.y - _SpeedDistortMap_ST.w)/_SpeedDistortMap_ST.y); + half distortStrength = - _SpeedDistortVec.x * 0.2; + distortUV = normalize(screenUV-_CustomScreenCenter.xy)*noise; + distortUVWithoutIntensity = distortUV; + distortUV *= distortStrength; + } + + + color.a += dot(distortUV,distortUV)*100000; + } + else + { + distortUVWithoutIntensity = disturbanceMask; + } + + // return half4(((dot(distortUV,distortUV)*100000)).rrr,1); + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_CHORATICABERRAT) || CheckLocalFlags(FLAG_BIT_RADIALBLUR)) + { + float2 blurVec = 0; + half dist = 0; + + if(!CheckLocalFlags(FLAG_BIT_CHORATICABERRAT_BY_DISTORT)|!CheckLocalFlags(FLAG_BIT_RADIALBLUR_BY_DISTORT)) + { + blurVec = _CustomScreenCenter.xy - screenUV; + dist = dot(blurVec,blurVec)*4; + } + + float2 choraticaBerratBlurVec; + if(CheckLocalFlags(FLAG_BIT_CHORATICABERRAT)) + { + if(CheckLocalFlags(FLAG_BIT_CHORATICABERRAT_BY_DISTORT)) + { + choraticaBerratBlurVec = distortUVWithoutIntensity; + } + else + { + choraticaBerratBlurVec = blurVec; + } + } + + + + + if(CheckLocalFlags(FLAG_BIT_RADIALBLUR)) + { + + float2 radialblurVec; + if(CheckLocalFlags(FLAG_BIT_RADIALBLUR_BY_DISTORT)) + { + radialblurVec = distortUVWithoutIntensity*_RadialBlurVec.x; + } + else + { + _RadialBlurVec.z *= 0.5; + half rangeIntensity = NB_Remap(dist,_RadialBlurVec.y-_RadialBlurVec.z,_RadialBlurVec.y+_RadialBlurVec.z,0,1); + rangeIntensity = saturate(rangeIntensity); + radialblurVec = blurVec*_RadialBlurVec.x*rangeIntensity; + } + color.a += dot(blurVec,blurVec)*100; + + half3 acumulateColor = half3(0, 0, 0); + + int iteration = _RadialBlurVec.w; + [unroll(12)] + for(int i = 0;i mats = new List(); + private Shader shader; + private MaterialEditor matEditor; + public List shaderFlags = new List(); + + private int lastFlagBit; + + // private bool isCustomedStencil = false;//isCustomStencil应该各个材质各自控制。 + private readonly int _isCustomedStencilPropID = Shader.PropertyToID("_CustomStencilTest"); + private readonly string _defaultStencilKey = "ParticleBaseDefault"; + + private StencilValuesConfig _stencilValuesConfig; + + private bool isInit = true; + + public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) + { + //一定要初始化在第一行 + mats.Clear(); + shaderFlags.Clear(); + for (int i = 0; i < materialEditor.targets.Length; i++) + { + var targetMat = materialEditor.targets[i] as Material; + + mats.Add(targetMat); + shaderFlags.Add(new W9ParticleShaderFlags(mats[i])); + + } + + if (!_stencilValuesConfig) + { + _stencilValuesConfig = + AssetDatabase.LoadAssetAtPath( + "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/StencilConfig.asset"); + } + + matEditor = materialEditor; + EditorGUIUtility.labelWidth = 180f; + _helper.Init(materialEditor, props, shaderFlags.ToArray(), mats); + _houdiniVatGui ??= new ParticleBaseHoudiniVATGUI(_helper); + _tyflowVatGui ??= new ParticleBaseTyflowVATGUI(_helper); + + if (isInit) + { + CacheRenderersUsingThisMaterial(mats[0],0);//应该只Cache这一次就可以了。 + isInit = false; + } + + _helper.DrawToolBar(); + EditorGUI.BeginChangeCheck(); + + _helper.DrawBigBlockFoldOut(W9ParticleShaderFlags.foldOutBitMeshOption, 3, GetAnimBoolIndex(3), "模式设置", + () => DrawMeshOptions(),false); + + _helper.DrawBigBlockFoldOut(W9ParticleShaderFlags.foldOutBitBaseOption, 3, GetAnimBoolIndex(3), "基本全局功能", + () => DrawBaseOptions(),false); + _helper.DrawBigBlockFoldOut(W9ParticleShaderFlags.foldOutBitMainTexOption, 3, GetAnimBoolIndex(3), "主贴图功能", + () => DrawMainTexOptions()); + + if (_uiEffectEnabled == 0 || _helper.ResetTool.IsInitResetData) + { + _helper.DrawBigBlockFoldOut(W9ParticleShaderFlags.foldOutBit1LightOption, 4, GetAnimBoolIndex(4), + "光照功能", () => DrawLightOptions()); + } + + _helper.DrawBigBlockFoldOut(W9ParticleShaderFlags.foldOutBitFeatureOption, 3, GetAnimBoolIndex(3), "特别功能", + () => DrawFeatureOptions()); + _helper.DrawBigBlockFoldOut(W9ParticleShaderFlags.foldOutBit1TaOption, 4, GetAnimBoolIndex(4), "TA调试", + () => DrawTaOptions()); + + EditorGUIUtility.labelWidth = 0f; + + if (mats.Count == 1) + { + if (_meshSourceMode == MeshSourceMode.Particle || _meshSourceMode == MeshSourceMode.UIParticle) + { + DoVertexStreamsArea(mats[0], m_ParticleRenderersUsingThisMaterial, 0); //填充stream和stremList + mats[0].EnableKeyword("_CUSTOMDATA"); + } + else + { + mats[0].DisableKeyword("_CUSTOMDATA"); + } + } + + if (EditorGUI.EndChangeCheck()) + { + DoAfterDraw(); + + //多选状态下同步ShaderFlag + if (mats.Count > 1) + { + for (int i = 1; i < mats.Count; i++) + { + mats[i].SetInteger(W9ParticleShaderFlags.foldOutFlagId, + mats[0].GetInteger(W9ParticleShaderFlags.foldOutFlagId)); + mats[i].SetInteger(W9ParticleShaderFlags.foldOutFlagId1, + mats[0].GetInteger(W9ParticleShaderFlags.foldOutFlagId1)); + mats[i].SetInteger(W9ParticleShaderFlags.foldOutFlagId2, + mats[0].GetInteger(W9ParticleShaderFlags.foldOutFlagId2)); + } + } + } + } + + int _uiEffectEnabled = -1; //0 false,1 true,-1 unKnow | MixedValue + int _meshSourceModeIsParticle = -1; //Particle Or UI Particle; + private int _useGraphicMainTex = -1; //UI Sprite/UI RawImage + int _noiseEnabled = -1; //扭曲 + private int _pNoiseEnabled = -1;//程序化噪波 + + private MeshSourceMode _meshSourceMode = MeshSourceMode.UnKnowOrMixed; + private TransparentMode _transparentMode = TransparentMode.UnKnowOrMixed; + + public void DrawMeshOptions() + { + + _helper.DrawPopUp("Mesh来源模式", "_MeshSourceMode", _meshSourceModeNames, drawBlock: modeProp => + { + + if (!modeProp.hasMixedValue) + { + _meshSourceMode = (MeshSourceMode)modeProp.floatValue; + } + else + { + _meshSourceMode = MeshSourceMode.UnKnowOrMixed; + } + + for (int i = 0; i < mats.Count; i++) + { + MeshSourceMode mode = (MeshSourceMode)mats[i].GetFloat("_MeshSourceMode"); + + int uiEffectEnabled; + int meshSourceModeIsParticle; + int useGraphicMainTex; + if (mode == MeshSourceMode.UIEffectRawImage || mode == MeshSourceMode.UIEffectSprite || + mode == MeshSourceMode.UIEffectBaseMap || mode == MeshSourceMode.UIParticle) + { + uiEffectEnabled = 1; + } + else + { + uiEffectEnabled = 0; + } + + if (mode == MeshSourceMode.Particle || mode == MeshSourceMode.UIParticle) + { + meshSourceModeIsParticle = 1; + } + else + { + meshSourceModeIsParticle = 0; + } + + if (mode == MeshSourceMode.UIEffectSprite || mode == MeshSourceMode.UIEffectRawImage) + { + useGraphicMainTex = 1; + } + else + { + useGraphicMainTex = 0; + } + + if (i == 0) + { + _uiEffectEnabled = uiEffectEnabled; + _meshSourceModeIsParticle = meshSourceModeIsParticle; + _useGraphicMainTex = useGraphicMainTex; + } + else + { + if (_uiEffectEnabled != uiEffectEnabled) + { + _uiEffectEnabled = -1; + } + + if (_meshSourceModeIsParticle != meshSourceModeIsParticle) + { + _meshSourceModeIsParticle = -1; + } + + if (_useGraphicMainTex != useGraphicMainTex) + { + _useGraphicMainTex = -1; + } + } + } + + if (checkIsParicleSystem) + { + if (_meshSourceModeIsParticle <= 0) + { + EditorGUILayout.HelpBox("检测到材质用在粒子系统上,和设置不匹配", MessageType.Error); + } + } + else + { + //这个不能Log,因为在Project面板下打开是不知道在不在粒子系统里的。 + // if (_meshSourceMode == MeshSourceMode.Particle) + // { + // EditorGUILayout.HelpBox("检测到材质没有用在粒子系统上,和设置不匹配",MessageType.Error); + // } + } + }); + + _helper.DrawPopUp("透明模式", "_TransparentMode", transparentModeNames, drawBlock: transModeProp => + { + if (!transModeProp.hasMixedValue) + { + _transparentMode = (TransparentMode)mats[0].GetFloat("_TransparentMode"); + if (_transparentMode == TransparentMode.CutOff||_helper.ResetTool.IsInitResetData) + { + // matEditor.ShaderProperty(_helper.GetProperty("_Cutoff"), "裁剪位置"); + _helper.DrawSlider("裁剪位置","_Cutoff"); + } + + if (_transparentMode == TransparentMode.Transparent||_helper.ResetTool.IsInitResetData) + { + _helper.DrawPopUp("混合模式", "_Blend", blendModeNames, drawBlock: blendProp => + { + if (!blendProp.hasMixedValue) + { + BlendMode blendMode = (BlendMode)blendProp.floatValue; + if (blendMode == BlendMode.Premultiply || blendMode == BlendMode.Additive||_helper.ResetTool.IsInitResetData) + { + _helper.DrawSlider("叠加到预乘混合","_AdditiveToPreMultiplyAlphaLerp",0,1); + } + } + + },drawOnValueChangedBlock: blendProp => { + if (!_helper.ResetTool.IsInitResetData) + { + BlendMode blendMode = (BlendMode)blendProp.floatValue; + MaterialProperty addToPreMultiplyAlphaLerpProp = + _helper.GetProperty("_AdditiveToPreMultiplyAlphaLerp"); + if (blendMode == BlendMode.Premultiply) + { + addToPreMultiplyAlphaLerpProp.floatValue = 1; + } + else if (blendMode == BlendMode.Additive) + { + addToPreMultiplyAlphaLerpProp.floatValue = 0; + } + } + }); + } + } + else + { + _transparentMode = TransparentMode.UnKnowOrMixed; + } + + }); + } + + public void DrawBaseOptions() + { + _helper.DrawFloat("整体颜色强度", "_BaseColorIntensityForTimeline"); + _helper.DrawSlider("整体透明度", "_AlphaAll", rangePropertyName:"AlphaAllRangeVec"); + _helper.DrawFoldOut(W9ParticleShaderFlags.foldOutBit2ColorAdjustment, 5, + GetAnimBoolIndex(5),"颜色调整",drawBlock: () => + { + _helper.DrawToggle("颜色调整仅影响主贴图","_ColorAdjustmentOnlyAffectMainTex",W9ParticleShaderFlags.FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitHueShift, 3, GetAnimBoolIndex(3), "色相偏移", + "_HueShift_Toggle", W9ParticleShaderFlags.FLAG_BIT_HUESHIFT_ON, isIndentBlock: true, + drawBlock: (isToggle) => + { + _helper.DrawSlider("色相", "_HueShift", 0, 1); + DrawCustomDataSelect("色相自定义曲线", W9ParticleShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT, 0); + }); + + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitSaturability, 3, GetAnimBoolIndex(3), + "饱和度", "_ChangeSaturability_Toggle", W9ParticleShaderFlags.FLAG_BIT_SATURABILITY_ON, + isIndentBlock: true, drawBlock: (isToggle) => + { + _helper.DrawSlider("饱和度", "_Saturability", rangePropertyName:"SaturabilityRangeVec"); + DrawCustomDataSelect("饱和度强度自定义曲线", W9ParticleShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_SATURATE, 1); + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit1MianTexContrast, 4, GetAnimBoolIndex(4), + "对比度", "_Contrast_Toggle", W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST, 1, + isIndentBlock: true, drawBlock: (isToggle) => + { + matEditor.ShaderProperty(_helper.GetProperty("_ContrastMidColor"), "对比度中值颜色"); + _helper.DrawSlider("对比度", "_Contrast", 0, 5); + DrawCustomDataSelect("对比度自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST, 2); + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit1MainTexColorRefine, 4, GetAnimBoolIndex(4), + "颜色修正", "_BaseMapColorRefine_Toggle", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE, 1, isIndentBlock: true, drawBlock: + (isToggle) => + { + _helper.DrawVector4Component("A:主颜色相乘", "_BaseMapColorRefine", "x", false); + _helper.DrawVector4Component("B:主颜色Power", "_BaseMapColorRefine", "y", false); + _helper.DrawVector4Component("B:主颜色Power后相乘", "_BaseMapColorRefine", "z", false); + _helper.DrawVector4Component("A/B线性差值", "_BaseMapColorRefine", "w", true, 0f, 1f); + }); + + _helper.DrawToggle("颜色乘透明度(改善锯齿)","_ColorMultiAlpha",W9ParticleShaderFlags.FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA); + }); + if (_uiEffectEnabled == 0) + { + _helper.DrawPopUp("深度测试", "_ZTest", Enum.GetNames(typeof(CompareFunction))); + } + else if (_uiEffectEnabled == 1) + { + _helper.GetProperty("_ZTest").floatValue = 4.0f; //UI层使用默认值LessEqual + } + + // _helper.DrawPopUp("时间模式","_TimeMode",Enum.GetNames(typeof(TimeMode))); + _helper.DrawPopUp("渲染面向", "_Cull", Enum.GetNames(typeof(RenderFace))); + + + + if (_uiEffectEnabled == 0) + { + + if (_transparentMode == TransparentMode.Transparent) + { + _helper.DrawToggle("预渲染反面", "_BackFirstPassToggle", drawBlock: (isToggle) => + { + if (!isToggle.hasMixedValue) + { + bool isBackFirstPass = isToggle.floatValue > 0.5f; + for (int i = 0; i < mats.Count; i++) + { + mats[i].SetShaderPassEnabled("SRPDefaultUnlit", isToggle.floatValue > 0.5f); + if (isBackFirstPass) + { + mats[i].SetFloat("_Cull", (float)RenderFace.Front); + } + } + + if (isBackFirstPass) + { + EditorGUILayout.HelpBox("预渲染反面会导致打断动态合批,请谨慎使用。", MessageType.Warning); + } + } + }); + + + } + _helper.DrawPopUp("深度写入强制控制", "_ForceZWriteToggle",_ForceZWriteToggleNames); + + _helper.DrawToggle("投射阴影", "_AffectsShadows", drawBlock: isToggle => + { + if (!isToggle.hasMixedValue && isToggle.floatValue > 0.5f && + _transparentMode == TransparentMode.Transparent) + { + _helper.DrawToggle("半透明 Dither 阴影", "_TransparentShadowDitherToggle"); + } + }); + + + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2BaseBackColor,5,GetAnimBoolIndex(5),"背面颜色", "_BaseBackColor_Toggle", W9ParticleShaderFlags.FLAG_BIT_PARTICLE_BACKCOLOR, + drawBlock: + (isToggle) => + { + // matEditor.ColorProperty(_helper.GetProperty("_BaseBackColor"), ""); + _helper.ColorProperty("背面颜色","_BaseBackColor"); + }); + + + } + + if (_uiEffectEnabled == 0) + { + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitDistanceFade, 3, GetAnimBoolIndex(3), "近距离透明", + "_DistanceFade_Toggle", W9ParticleShaderFlags.FLAG_BIT_PARTICLE_DISTANCEFADE_ON, + isIndentBlock: true, drawBlock: (isToggle) => + { + _helper.DrawVector4In2Line("_Fade", "透明过度范围", true); + }); + } + else + { + for (int i = 0; i < mats.Count; i++) + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_DISTANCEFADE_ON); + } + } + + if (_uiEffectEnabled == 0) + { + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitSoftParticles, 3, GetAnimBoolIndex(3), "软粒子", + "_SoftParticlesEnabled", shaderKeyword: "_SOFTPARTICLES_ON", isIndentBlock: true, drawBlock: + (isToggle) => + { + _helper.DrawVector4In2Line("_SoftParticleFadeParams", "远近裁剪面", true); + }); + + + + _helper.DrawToggle("剔除主角色", "_StencilWithoutPlayerToggle", shaderKeyword: "_STENCIL_WITHOUT_PLAYER", + drawEndChangeCheck: isToggle => + { + if (!isToggle.hasMixedValue) + { + for (int i = 0; i < mats.Count; i++) + { + if (isToggle.floatValue > 0.5f) + { + StencilTestHelper.SetMaterialStencil(mats[i], "ParticleWithoutPlayer", + _stencilValuesConfig, out int queue); + mats[i].SetFloat(_isCustomedStencilPropID, 1.0f); + } + else + { + StencilTestHelper.SetMaterialStencil(mats[i], _defaultStencilKey, + _stencilValuesConfig, out int queue); + mats[i].SetFloat(_isCustomedStencilPropID, 0.0f); + } + } + } + }); + _helper.DrawToggle("忽略顶点色", "_IgnoreVetexColor_Toggle", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR, flagIndex: 1); + _helper.DrawSlider("雾影响强度", "_fogintensity", 0f, 1f); + } + else if (_uiEffectEnabled == 1) + { + _helper.GetProperty("_fogintensity").floatValue = 0; + } + } + + public void DrawMainTexOptions() + { + Action drawAfterMainTex = () => + { + DrawColorChannelSelect("主贴图透明度通道", W9ParticleShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA,3); + if (_meshSourceMode != MeshSourceMode.UIEffectSprite) + { + MaterialProperty textureProp = null; + if (_meshSourceMode == MeshSourceMode.UIEffectRawImage) + { + textureProp = _helper.GetProperty("_MainTex"); + } + else + { + textureProp = _helper.GetProperty("_BaseMap"); + } + + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeMainTex, 4, "主贴图UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_MAINTEX, 0, textureProp: textureProp); + } + + DrawCustomDataSelect("主贴图X轴偏移自定义曲线", W9ParticleShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X, + 0); + DrawCustomDataSelect("主贴图Y轴偏移自定义曲线", W9ParticleShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y, + 0); + + if (_meshSourceMode != MeshSourceMode.UIEffectSprite) + { + + _helper.DrawVector4In2Line("_BaseMapMaskMapOffset", "偏移速度", true); + _helper.DrawSlider("主贴图旋转", "_BaseMapUVRotation", 0f, 360f); + _helper.DrawFloat("主贴图旋转速度","_BaseMapUVRotationSpeed"); + } + + DrawNoiseAffectBlock(() => + { + _helper.DrawSlider("主贴图扭曲强度控制", "_TexDistortion_intensity",rangePropertyName: "TexDistortionintensityRangeVec"); + + }); + + + + }; + + Action drawBaseMapFoldOut = () => { + _helper.DrawTextureFoldOut(W9ParticleShaderFlags.foldOutBitBaseMap, 3, GetAnimBoolIndex(3), "主贴图", + "_BaseMap", "_BaseColor", drawWrapMode: true, + flagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_BASEMAP, flagIndex: 2, drawBlock: + theBaseMap => + { + drawAfterMainTex(); + });}; + Action drawUITextureModify = () => + { + _helper.ColorProperty( "贴图颜色叠加","_Color"); + _helper.DrawVector4In2Line("_UI_MainTex_ST", "Tilling", true); + _helper.DrawVector4In2Line("_UI_MainTex_ST", "Offset", false); + drawAfterMainTex(); + }; + + if (_helper.ResetTool.IsInitResetData) + { + drawBaseMapFoldOut(); + drawUITextureModify(); + } + else + { + if (_useGraphicMainTex <= 0) + { + drawBaseMapFoldOut(); + // _helper.DrawTexture("主贴图","_BaseMap","_BaseColor",drawWrapMode:true,flagBitsName:W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_BASEMAP,flagIndex:2); + } + else + { + drawUITextureModify(); + //实际上贴图来自_MainTex + } + } + + + } + + private MaterialProperty[] rampColorPropArr = new MaterialProperty[6]; + private MaterialProperty[] rampColorAlphaPropArr = new MaterialProperty[3]; + + private MaterialProperty[] maskMapGradientPropArr = new MaterialProperty[3]; + private MaterialProperty[] maskMap2GradientPropArr = new MaterialProperty[3]; + private MaterialProperty[] maskMap3GradientPropArr = new MaterialProperty[3]; + + private MaterialProperty[] dissolveRampColorPropArr = new MaterialProperty[6]; + private MaterialProperty[] dissolveRampAlphaPropArr = new MaterialProperty[3]; + + private FxLightMode _fxLightMode; + + public void DrawLightOptions() + { + _helper.DrawPopUp("光照类型", "_FxLightMode", _fxLightModeNames, drawBlock: mode => + { + if (!mode.hasMixedValue) + { + _fxLightMode = (FxLightMode)mode.floatValue; + if (_fxLightMode == FxLightMode.BlinnPhong || _fxLightMode == FxLightMode.PBR || _fxLightMode == FxLightMode.HalfLambert||_helper.ResetTool.IsInitResetData) + { + if (_fxLightMode == FxLightMode.BlinnPhong || _fxLightMode == FxLightMode.HalfLambert||_helper.ResetTool.IsInitResetData) + { + _helper.DrawToggle("高光开关", "_BlinnPhongSpecularToggle", shaderKeyword: "_SPECULAR_COLOR", + drawBlock: + isToggle => + { + if ((!isToggle.hasMixedValue && isToggle.floatValue > 0.5f)||_helper.ResetTool.IsInitResetData) + { + _helper.ColorProperty("高光颜色","_SpecularColor"); + _helper.DrawVector4Component("光滑度", "_MaterialInfo", "y", true, 0, 1); + + } + }); + } + + if (_fxLightMode == FxLightMode.PBR||_helper.ResetTool.IsInitResetData) + { + _helper.DrawVector4Component("金属度", "_MaterialInfo", "x", true, 0, 1); + _helper.DrawVector4Component("光滑度", "_MaterialInfo", "y", true, 0, 1); + } + } + if (_fxLightMode == FxLightMode.SixWay||_helper.ResetTool.IsInitResetData) + { + _helper.DrawTexture("六路正方向图(P)", "_RigRTBk", drawScaleOffset: false); + _helper.DrawTexture("六路反方向图(N)", "_RigLBtF", drawScaleOffset: false); + + EditorGUILayout.HelpBox("六路UV跟随主贴图UV及颜色", MessageType.Warning); + + _helper.DrawToggle("光照颜色吸收", "_SixWayColorAbsorptionToggle", + shaderKeyword: "VFX_SIX_WAY_ABSORPTION", drawBlock: + isAbsorption => + { + _helper.DrawVector4Component("六路吸收强度", "_SixWayInfo", "x", true, 0, 1); + }); + + _helper.DrawTexture("六路自发光Ramp", "_SixWayEmissionRamp", drawScaleOffset: false, + drawBlock: rampMap => + { + if (!rampMap.hasMixedValue) + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (rampMap.textureValue) + { + shaderFlags[i] + .SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP, + index: 1); + } + else + { + shaderFlags[i] + .ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP, + index: 1); + } + } + } + }); + _helper.DrawVector4Component("六路自发光Pow", "_SixWayInfo", "y", false); + _helper.ColorProperty("六路自发光颜色","_SixWayEmissionColor"); + } + } + else + { + _fxLightMode = FxLightMode.UnKnownOrMixedValue; + } + + }); + + + if (_fxLightMode != FxLightMode.SixWay||_helper.ResetTool.IsInitResetData) + { + //--------------法线----------------- + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2BumpTexToggle, 5, GetAnimBoolIndex(5), + "法线贴图开关", "_BumpMapToggle", shaderKeyword: "_NORMALMAP", drawBlock: isBumpMapToggle => + { + MaterialProperty bumpTexFollowMainTexUVToggle = _helper.GetProperty("_BumpTexFollowMainTexUVToggle"); + _helper.DrawTextureFoldOut(W9ParticleShaderFlags.foldOutBit1BumpTex, 4, GetAnimBoolIndex(4), + "法线贴图", "_BumpTex", + flagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_BUMPTEX, + drawBlock: theBumpmap => + { + + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeBumpTex, 4, "法线贴图UV来源", W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_BUMPMAP, 0, theBumpmap); + + //在DoAfterDraw会执行SetKeyword的逻辑。 + _helper.DrawToggle("法线贴图多通道模式", "_BumpMapMaskMode", W9ParticleShaderFlags.FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE); + _helper.DrawSlider("法线强度", "_BumpScale", rangePropertyName:"BumpScaleRangeVec"); + }); + }); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2MatCapToggle, 5, GetAnimBoolIndex(5), + "MatCap模拟材质", "_MatCapToggle", shaderKeyword: "_MATCAP", drawBlock: isMatCapToggle => + { + _helper.DrawTexture("MatCap图", "_MatCapTex",colorPropertyName:"_MatCapColor", drawScaleOffset: false); + // matEditor.ColorProperty(_helper.GetProperty("_MatCapColor"), "MatCap颜色"); + _helper.DrawVector4Component("MatCap相加到相乘过渡", "_MatCapInfo", "x", true); + }); + + } + else if (_fxLightMode == FxLightMode.SixWay) + { + //这里应该关掉法线和Matcap的Keyword + } + } + + public void DrawFeatureOptions() + { + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitMask, 3, GetAnimBoolIndex(3), "遮罩", + "_Mask_Toggle", shaderKeyword: "_MASKMAP_ON", fontStyle: FontStyle.Bold, drawBlock: (isToggle) => + { + _helper.DrawToggle("测试遮罩颜色","_NB_Debug_Mask",shaderKeyword:"NB_DEBUG_MASK"); + _helper.DrawVector4Component("遮罩强度", "_MaskMapVec", "x", true); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2MaskRefine,5,GetAnimBoolIndex(5),"遮罩整体调整","_MaskRefineToggle",W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASK_REFINE,1,drawBlock: + maskRefineProp => + { + _helper.DrawVector4Component("范围(Pow)","_MaskRefineVec","x",false); + _helper.DrawVector4Component("相乘","_MaskRefineVec","y",false); + _helper.DrawVector4Component("偏移(相加)","_MaskRefineVec","z",false); + }); + DrawPNoiseBlendModeSelect("遮罩",W9ParticleShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_MASK,"_MaskPNoiseBlendOpacity"); + _helper.DrawPopUp("遮罩模式", "_MaskMapGradientToggle", _maskMapModeNames, + drawBlock: maskMapModeProp => + { + Action drawMaskTexturePart = () => + { + _helper.DrawTextureFoldOut(W9ParticleShaderFlags.foldOutBitMaskMap, 3, + GetAnimBoolIndex(3), "遮罩", "_MaskMap", drawWrapMode: true, + flagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP, flagIndex: 2, + drawBlock: theMaskMap => + { + DrawColorChannelSelect("遮罩通道选择", W9ParticleShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1); + }); + }; + Action drawMaskGradientPart = () => + { + maskMapGradientPropArr[0] = _helper.GetProperty("_MaskMapGradientFloat0"); + maskMapGradientPropArr[1] = _helper.GetProperty("_MaskMapGradientFloat1"); + maskMapGradientPropArr[2] = _helper.GetProperty("_MaskMapGradientFloat2"); + _helper.DrawGradient(false, ColorSpace.Gamma, "遮罩渐变", 6, + "_MaskMapGradientCount", alphaProperties: maskMapGradientPropArr); + _helper.TextureScaleOffsetProperty("_MaskMap"); + _helper.DrawWrapMode("遮罩", W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP, + flagIndex: 2); + }; + if (_helper.ResetTool.IsInitResetData) + { + drawMaskTexturePart(); + drawMaskGradientPart(); + } + else + { + if (!maskMapModeProp.hasMixedValue) + { + //绘制贴图 + if (maskMapModeProp.floatValue < 0.5f) + { + drawMaskTexturePart(); + } + else + { + drawMaskGradientPart(); + } + } + } + + + + }, drawOnValueChangedBlock: maskMapModeProp => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (maskMapModeProp.floatValue < 0.5f) + { + shaderFlags[i] + .ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT, + index: 1); + } + else + { + shaderFlags[i] + .SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT, + index: 1); + } + } + }); + + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeMaskMap, 4, "遮罩UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP, 0); + DrawCustomDataSelect("Mask图X轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X, 0); + DrawCustomDataSelect("Mask图Y轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y, 0); + _helper.DrawVector4In2Line("_MaskMapOffsetAnition", "遮罩偏移速度", true); + _helper.DrawFloat("遮罩旋转", "_MaskMapUVRotation"); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitMaskRotate, 3, + GetAnimBoolIndex(3), "遮罩旋转速度", "_Mask_RotationToggle", W9ParticleShaderFlags + .FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON, isIndentBlock: false, + drawBlock: (isToggle2) => + { + _helper.DrawFloat("旋转速度", "_MaskMapRotationSpeed"); + }); + + DrawNoiseAffectBlock(() => + { + _helper.DrawSlider("遮罩扭曲强度", "_MaskDistortion_intensity", rangePropertyName:"MaskDistortionIntensityRangeVec"); + }); + + + + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitMask2, 3, GetAnimBoolIndex(3), "遮罩2", + "_Mask2_Toggle", flagBitsName: W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASK_MAP2, + flagIndex: 1, isIndentBlock: true, drawBlock: + (isToggle) => + { + _helper.DrawPopUp("遮罩2模式", "_MaskMap2GradientToggle", _maskMapModeNames, + drawBlock: maskMap2GradientModeProp => + { + Action drawMask2TexturePart = () => + { + _helper.DrawTexture("遮罩2贴图", "_MaskMap2", drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP2, + flagIndex: 2, + drawBlock: theMaskMap2Texture => + { + DrawColorChannelSelect("遮罩2通道选择", + W9ParticleShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2); + }); + }; + Action drawMask2GradientPart = () => + { + maskMap2GradientPropArr[0] = _helper.GetProperty("_MaskMap2GradientFloat0"); + maskMap2GradientPropArr[1] = _helper.GetProperty("_MaskMap2GradientFloat1"); + maskMap2GradientPropArr[2] = _helper.GetProperty("_MaskMap2GradientFloat2"); + _helper.DrawGradient(false, ColorSpace.Gamma, + "遮罩2渐变(UV纵向)", 6, "_MaskMap2GradientCount", + alphaProperties: maskMap2GradientPropArr); + matEditor.TextureScaleOffsetProperty(_helper.GetProperty("_MaskMap2")); + _helper.DrawWrapMode("遮罩2UV", + W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP2, flagIndex: 2); + }; + if (_helper.ResetTool.IsInitResetData) + { + drawMask2TexturePart(); + drawMask2GradientPart(); + } + else + { + if (!maskMap2GradientModeProp.hasMixedValue) + { + if (maskMap2GradientModeProp.floatValue < 0.5f) + { + drawMask2TexturePart(); + } + else + { + drawMask2GradientPart(); + } + } + } + + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeMaskMap2, 4, "遮罩2UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP_2, 0); + _helper.DrawVector4Component("遮罩2旋转","_MaskMapVec","y",false); + _helper.DrawVector4In2Line("_MaskMapOffsetAnition", "遮罩2偏移速度", false); + }, drawOnValueChangedBlock: maskMap2GradientModeProp => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (maskMap2GradientModeProp.floatValue < 0.5f) + { + shaderFlags[i] + .ClearFlagBits( + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT, + index: 1); + } + else + { + shaderFlags[i] + .SetFlagBits( + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT, + index: 1); + } + } + + }); + + }); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitMask3, 3, GetAnimBoolIndex(3), "遮罩3", + "_Mask3_Toggle", flagBitsName: W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASK_MAP3, + flagIndex: 1, isIndentBlock: true, drawBlock: + (isToggle) => + { + _helper.DrawPopUp("遮罩3模式", "_MaskMap3GradientToggle", _maskMapModeNames, + drawBlock: maskMap3GradientModeProp => + { + Action drawMask3TexturePart = () => + { + _helper.DrawTexture("遮罩3贴图", "_MaskMap3", drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP3, + flagIndex: 2, + drawBlock: theMaskMap2Texture => + { + DrawColorChannelSelect("遮罩3通道选择", + W9ParticleShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3); + }); + }; + Action drawMask3GradientPart = () => + { + maskMap3GradientPropArr[0] = _helper.GetProperty("_MaskMap3GradientFloat0"); + maskMap3GradientPropArr[1] = _helper.GetProperty("_MaskMap3GradientFloat1"); + maskMap3GradientPropArr[2] = _helper.GetProperty("_MaskMap3GradientFloat2"); + _helper.DrawGradient(false, ColorSpace.Gamma, + "遮罩3渐变(UV横向)", 6, "_MaskMap3GradientCount", + alphaProperties: maskMap3GradientPropArr); + matEditor.TextureScaleOffsetProperty(_helper.GetProperty("_MaskMap3")); + _helper.DrawWrapMode("遮罩3UV", + W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP3, flagIndex: 2); + }; + if (_helper.ResetTool.IsInitResetData) + { + drawMask3TexturePart(); + drawMask3GradientPart(); + } + else + { + if (!maskMap3GradientModeProp.hasMixedValue) + { + if (maskMap3GradientModeProp.floatValue < 0.5f) + { + drawMask3TexturePart(); + } + else + { + drawMask3GradientPart(); + } + } + } + + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeMaskMap3, 4, "遮罩3UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP_3, 0); + _helper.DrawVector4Component("遮罩3旋转","_MaskMapVec","z",false); + + _helper.DrawVector4In2Line("_MaskMap3OffsetAnition", "遮罩3偏移速度", true); + }, drawOnValueChangedBlock: maskMap3GradientModeProp => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (maskMap3GradientModeProp.floatValue < 0.5f) + { + shaderFlags[i] + .ClearFlagBits( + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT, + index: 1); + } + else + { + shaderFlags[i] + .SetFlagBits( + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT, + index: 1); + } + } + + }); + }); + }); + + + MaterialProperty noiseToggleProperty = _helper.GetProperty("_noisemapEnabled"); + if (noiseToggleProperty.hasMixedValue) + { + _noiseEnabled = -1; + } + else + { + _noiseEnabled = noiseToggleProperty.floatValue > 0.5f ? 1 : 0; + } + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitNoise, 3, GetAnimBoolIndex(3), "扭曲", + "_noisemapEnabled", shaderKeyword: "_NOISEMAP", fontStyle: FontStyle.Bold, + drawBlock: (isToggle) => + { + _helper.DrawToggle("扭曲强度值测试","_NB_Debug_Distort",shaderKeyword:"NB_DEBUG_DISTORT"); + _helper.DrawSlider("整体扭曲强度", "_NoiseIntensity", rangePropertyName:"_NoiseIntensityRangeVec"); + DrawCustomDataSelect("扭曲强度自定义曲线", W9ParticleShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY, 1); + if (!(_uiEffectEnabled>0.5f) || _helper.ResetTool.IsInitResetData) + { + _helper.DrawPopUp("屏幕扰动模式","_ScreenDistortModeToggle",screenDistortModeNames,drawBlock: + scrDistortModeProp => + { + if (scrDistortModeProp.floatValue > 0.5f || _helper.ResetTool.IsInitResetData) + { + EditorGUI.indentLevel++; + _helper.DrawSlider("屏幕扭曲强度", "_ScreenDistortIntensity", rangePropertyName:"_ScreenDistortIntensityRangeVec"); + _helper.DrawToggle("关闭主材质Pass","_DisableMainPassToggle",drawEndChangeCheck: + disableMainPassToggleProp => + { + for (int i = 0; i < mats.Count; i++) + { + mats[i].SetShaderPassEnabled("UniversalForward",disableMainPassToggleProp.floatValue < 0.5f); + } + }); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2ScreenDistortAlphaRefine,5,GetAnimBoolIndex(5),"屏幕扭曲Alpha整体调整","_ScreenDistortAlphaRefineToggle",W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE,1,drawBlock: + AlphaRefineProp => + { + _helper.DrawFloat("范围(Pow)", "_ScreenDistortAlphaPow"); + _helper.DrawFloat("相乘", "_ScreenDistortAlphaMulti"); + _helper.DrawFloat("偏移(相加)", "_ScreenDistortAlphaAdd"); + }); + + EditorGUI.indentLevel--; + } + + },drawOnValueChangedBlock: + screenDistortModeProp => + { + ScreenDistortMode screenDistortMode = (ScreenDistortMode)screenDistortModeProp.floatValue; + for (int i = 0; i < mats.Count; i++) + { + switch (screenDistortMode) + { + case ScreenDistortMode.None: + mats[i].SetShaderPassEnabled("NBCameraOpaqueDistortPass", false); + mats[i].SetShaderPassEnabled("NBDeferredDistortPass", false); + //打开主材质Pass + mats[i].SetShaderPassEnabled("UniversalForward",true); + if (i == 0) _helper.GetProperty("_DisableMainPassToggle").floatValue = 0; + + break; + case ScreenDistortMode.CameraOpaqueDistort: + mats[i].SetShaderPassEnabled("NBCameraOpaqueDistortPass", true); + mats[i].SetShaderPassEnabled("NBDeferredDistortPass", false); + break; + case ScreenDistortMode.DeferredDistort: + mats[i].SetShaderPassEnabled("NBCameraOpaqueDistortPass", false); + mats[i].SetShaderPassEnabled("NBDeferredDistortPass", true); + break; + //在OnvalueChange后不会有Mixed的情况 + } + } + }); + } + + + _helper.DrawPopUp("扭曲模式","_DistortMode",distortModeNames,drawBlock: modeProp => + { + if((!modeProp.hasMixedValue && Mathf.Approximately(modeProp.floatValue,0))||_helper.ResetTool.IsInitResetData) + { + EditorGUILayout.LabelField("扭曲贴图RG双通道则为FlowMap,FlowMap贴图设置应该去掉sRGB勾选"); + _helper.DrawTextureFoldOut(W9ParticleShaderFlags.foldOutBitNoiseMap, 3, GetAnimBoolIndex(3), "扭曲贴图", + "_NoiseMap", drawWrapMode: true, flagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_NOISEMAP, + flagIndex: 2, drawBlock: + theNoiseMap => + { + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeNoiseMap, 4, "扭曲贴图UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_NOISE_MAP, 0, theNoiseMap); + + _helper.DrawVector4In2Line("_DistortionDirection", "扭曲方向强度", true); + DrawCustomDataSelect("扭曲方向强度X自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X, 2); + DrawCustomDataSelect("扭曲方向强度Y自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y, 2); + + _helper.DrawSlider("扭曲旋转", "_NoiseMapUVRotation", 0f, 360f); + _helper.DrawVector4In2Line("_NoiseOffset", "扭曲偏移速度", true); + _helper.DrawToggle("0.5为中值,双向扭曲", "_DistortionBothDirection_Toggle", + flagBitsName: W9ParticleShaderFlags.FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON, + isIndentBlock: false); + }); + } + + if((!modeProp.hasMixedValue && Mathf.Approximately(modeProp.floatValue,1))||_helper.ResetTool.IsInitResetData) + { + _helper.DrawSlider("折射率", "_RefractionIOR", 0f, 5f); + + } + + },drawOnValueChangedBlock: modePropOnValueChanged => + { + for (int i = 0; i < mats.Count; i++) + { + if (Mathf.Approximately(modePropOnValueChanged.floatValue, 1)) + { + mats[i].EnableKeyword("_DISTORT_REFRACTION"); + } + else + { + mats[i].DisableKeyword("_DISTORT_REFRACTION"); + } + } + }); + + DrawPNoiseBlendModeSelect("扭曲",W9ParticleShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT,"_DistortPNoiseBlendOpacity"); + + + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitNoiseMaskToggle, 3, GetAnimBoolIndex(3), + "扭曲遮罩", "_noiseMaskMap_Toggle", + flagBitsName: W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_NOISE_MASKMAP, flagIndex: 1, + drawBlock: isNoiseMaskToggle => + { + _helper.DrawTexture("扭曲遮罩贴图", "_NoiseMaskMap", drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_NOISE_MASKMAP, drawBlock: + theNoiseMaskMap => + { + DrawColorChannelSelect("扭曲遮罩图通道选择", + W9ParticleShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK); + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeNoiseMaskMap, 4, + "扭曲遮罩贴图UV来源", W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP, 0, + theNoiseMaskMap); + }); + }); + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitDistortionChoraticaberrat, 3, GetAnimBoolIndex(3), + "扭曲色散", "_Distortion_Choraticaberrat_Toggle", W9ParticleShaderFlags.FLAG_BIT_PARTICLE_CHORATICABERRAT, + isIndentBlock: true, fontStyle: FontStyle.Bold, drawBlock: + (is_Choraticaberrat_Toggle) => + { + DrawNoiseAffectBlock(() => + { + _helper.DrawToggle("色散强度受扭曲强度影响", "_Distortion_Choraticaberrat_WithNoise_Toggle", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE); + }); + _helper.DrawVector4Component("色散强度", "_DistortionDirection", "z", false); + DrawCustomDataSelect("色散强度自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY, 0); + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitEmission, 3, GetAnimBoolIndex(3), "流光(颜色相加)", + "_EmissionEnabled", shaderKeyword: "_EMISSION", isIndentBlock: true, fontStyle: FontStyle.Bold, + drawBlock: (isToggle) => + { + _helper.DrawTexture("流光贴图", "_EmissionMap", "_EmissionMapColor",drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_EMISSIONMAP, flagIndex: 2, + drawBlock: theEmissionMap => + { + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeEmissionMap, 4, "流光贴图UV来源", W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_EMISSION_MAP, 0, theEmissionMap); + DrawCustomDataSelect("流光贴图X轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X, 3); + DrawCustomDataSelect("流光贴图Y轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y, 3); + _helper.DrawSlider("流光贴图旋转", "_EmissionMapUVRotation", 0f, 360f); + _helper.DrawVector4In2Line("_EmissionMapUVOffset", "流光贴图偏移速度", true); + DrawNoiseAffectBlock(() => { _helper.DrawSlider("流光贴图扭曲强度", "_Emi_Distortion_intensity",rangePropertyName:"EmiDistortionIntensityRangeVec"); }); + + }); + _helper.DrawFloat("流光颜色强度", "_EmissionMapColorIntensity"); + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutColorBlend, 3, GetAnimBoolIndex(3), "渐变(颜色相乘)", + "_ColorBlendMap_Toggle", shaderKeyword: "_COLORMAPBLEND", isIndentBlock: true, + fontStyle: FontStyle.Bold, + drawBlock: (isToggle) => + { + _helper.DrawTexture("颜色渐变贴图", "_ColorBlendMap",colorPropertyName:"_ColorBlendColor" ,drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_COLORBLENDMAP, flagIndex: 2, + drawBlock: texProp => + { + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeColorBlendMap, 4, "颜色渐变贴图UV来源", W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP, 0, texProp); + DrawCustomDataSelect("颜色渐变贴图X轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X, 3); + DrawCustomDataSelect("颜色渐变贴图Y轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y, 3); + _helper.DrawVector4Component("颜色渐变贴图旋转", "_ColorBlendVec", "w", true, 0f, 360f); + _helper.DrawVector4In2Line("_ColorBlendMapOffset", "颜色渐变贴图偏移速度", true); + DrawNoiseAffectBlock(() => { _helper.DrawVector4Component("颜色渐变扭曲强度","_ColorBlendVec","x",true,0f,1f); }); + + }); + _helper.DrawPopUp("颜色渐变图Alpha作用","_ColorBlendAlphaMultiplyMode",colorBlendAlphaMode,drawOnValueChangedBlock: + alphaModeProp => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (alphaModeProp.floatValue > 0.5) + { + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE); + } + else + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE); + } + + } + }); + _helper.DrawVector4Component("颜色渐变图Alpha强度","_ColorBlendVec","z",true,0f,1f); + + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2RampColor, 5, GetAnimBoolIndex(5), "颜色映射(Ramp)", + "_RampColorToggle", shaderKeyword: "_COLOR_RAMP", isIndentBlock: true, fontStyle: FontStyle.Bold, + drawBlock: + isToggleProp => + { + _helper.DrawPopUp("Ramp来源模式", "_RampColorSourceMode", rampColorSourceMode, + drawBlock: modeProp => + { + Action drawRampTexture = () => + { + _helper.DrawTexture("颜色映射黑白图", "_RampColorMap", drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP, + flagIndex: 2, + drawBlock: texProp => + { + DrawColorChannelSelect("颜色映射黑白图通道选择", + W9ParticleShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP); + }); + }; + Action drawNoRampTexture = () => + { + _helper.TextureScaleOffsetProperty("_RampColorMap"); + _helper.DrawWrapMode("颜色映射UV", + W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP, 2); + }; + if (_helper.ResetTool.IsInitResetData) + { + drawRampTexture(); + drawNoRampTexture(); + } + else + { + if (!modeProp.hasMixedValue) + { + if (modeProp.floatValue >= 0.5f) + { + drawRampTexture(); + } + else + { + drawNoRampTexture(); + } + } + } + }, drawOnValueChangedBlock: modeProp => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (modeProp.floatValue > 0.5f) + { + shaderFlags[i] + .SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_RAMP_COLOR_MAP_MODE_ON); + } + else + { + shaderFlags[i] + .ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_RAMP_COLOR_MAP_MODE_ON); + } + } + }); + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeRampColorMap, 4, "颜色映射黑白图UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP, 0, + _helper.GetProperty("_RampColorMap"),forceEnable:true); + _helper.DrawVector4In2Line("_RampColorMapOffset", "颜色映射贴图偏移速度", true); + _helper.DrawVector4Component("颜色映射贴图旋转", "_RampColorMapOffset", "w", true, 0f, 360f); + rampColorPropArr[0] = _helper.GetProperty("_RampColor0"); + rampColorPropArr[1] = _helper.GetProperty("_RampColor1"); + rampColorPropArr[2] = _helper.GetProperty("_RampColor2"); + rampColorPropArr[3] = _helper.GetProperty("_RampColor3"); + rampColorPropArr[4] = _helper.GetProperty("_RampColor4"); + rampColorPropArr[5] = _helper.GetProperty("_RampColor5"); + rampColorAlphaPropArr[0] = _helper.GetProperty("_RampColorAlpha0"); + rampColorAlphaPropArr[1] = _helper.GetProperty("_RampColorAlpha1"); + rampColorAlphaPropArr[2] = _helper.GetProperty("_RampColorAlpha2"); + _helper.DrawGradient(true, ColorSpace.Gamma, "映射颜色", 6, "_RampColorCount", + rampColorPropArr, rampColorAlphaPropArr); + _helper.DrawPopUp("Ramp颜色混合模式", "_RampColorBlendMode", rampColorBlendMode, drawOnValueChangedBlock: + modeProp => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (modeProp.floatValue > 0.5f) + { + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags + .FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD); + } + else + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags + .FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD); + } + } + }); + matEditor.ShaderProperty(_helper.GetProperty("_RampColorBlendColor"), "颜色映射叠加颜色_hdr"); + + + }); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutDissolve, 3, GetAnimBoolIndex(3), "溶解", + "_Dissolve_Toggle", shaderKeyword: "_DISSOLVE", isIndentBlock: true, fontStyle: FontStyle.Bold, + drawBlock: (isToggle) => + { + + _helper.DrawToggle("溶解度黑白值测试", "_NB_Debug_Dissolve", shaderKeyword: "NB_DEBUG_DISSOLVE"); + _helper.DrawTextureFoldOut(W9ParticleShaderFlags.foldOutDissolveMap, 3, GetAnimBoolIndex(3), "溶解贴图", + "_DissolveMap", drawScaleOffset: true, drawWrapMode: true, + flagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_MAP, flagIndex: 2, + drawBlock: (dissolveTex) => + { + DrawColorChannelSelect("溶解贴图通道选择", + W9ParticleShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP); + // matEditor.TextureScaleOffsetProperty(_helper.GetProperty("_DissolveMap")); + DrawCustomDataSelect("溶解贴图X轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X, 1); + DrawCustomDataSelect("溶解贴图Y轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y, 1); + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeDissolveMap, 4, "溶解贴图UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP, 0, dissolveTex); + _helper.DrawVector4In2Line("_DissolveOffsetRotateDistort", "溶解贴图偏移速度", true); + _helper.DrawVector4Component("溶解贴图旋转", "_DissolveOffsetRotateDistort", "z", true, 0f, 360f); + }); + DrawPNoiseBlendModeSelect("溶解",W9ParticleShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE,"_DissolvePNoiseBlendOpacity"); + _helper.DrawVector4Component("溶解值Pow", "_Dissolve","y",true,0f,10f); + _helper.DrawVector4Component("溶解强度", "_Dissolve", "x", true, rangeVecPropName:"DissolveXRangeVec"); + DrawCustomDataSelect("溶解强度自定义曲线", W9ParticleShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY, + 0); + _helper.DrawVector4Component("溶解硬软度", "_Dissolve", "w", true, 0.001f, 1f); + DrawNoiseAffectBlock(() => + { + _helper.DrawVector4Component("溶解贴图扭曲强度", "_DissolveOffsetRotateDistort", "w", false); + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2DissolveLine,5,GetAnimBoolIndex(5),"溶解描边","_DissolveLineMaskToggle",W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK,1,drawBlock: + isDissolveLineMask => + { + // matEditor.ColorProperty(_helper.GetProperty("_DissolveLineColor"), "溶解描边颜色"); + _helper.ColorProperty("溶解描边颜色","_DissolveLineColor"); + _helper.DrawVector4Component("描边位置","_Dissolve_Vec2","x",true,rangeVecPropName:"Dissolve2XRangeVec"); + _helper.DrawVector4Component("描边软硬","_Dissolve_Vec2","y",true,rangeVecPropName:"Dissolve2YRangeVec"); + + }); + + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutDissolveRampMap, 3, GetAnimBoolIndex(3), + "溶解Ramp图功能", "_Dissolve_useRampMap_Toggle", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_DISSOVLE_USE_RAMP, flagIndex: 1, isIndentBlock: true, + drawBlock: + isDissolveUseRampToggle => + { + _helper.DrawPopUp("溶解Ramp模式", "_DissolveRampSourceMode", dissolveRampSourceMode, + drawBlock: dissolveRampModeProp => + { + Action drawRampTexture = () => + { + _helper.DrawTexture("溶解Ramp图", "_DissolveRampMap", "_DissolveRampColor", + drawScaleOffset: true, drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags + .FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP, flagIndex: 2); + }; + Action drawRampGradient = () => + { + dissolveRampColorPropArr[0] = _helper.GetProperty("_DissolveRampColor0"); + dissolveRampColorPropArr[1] = _helper.GetProperty("_DissolveRampColor1"); + dissolveRampColorPropArr[2] = _helper.GetProperty("_DissolveRampColor2"); + dissolveRampColorPropArr[3] = _helper.GetProperty("_DissolveRampColor3"); + dissolveRampColorPropArr[4] = _helper.GetProperty("_DissolveRampColor4"); + dissolveRampColorPropArr[5] = _helper.GetProperty("_DissolveRampColor5"); + dissolveRampAlphaPropArr[0] = _helper.GetProperty("_DissolveRampAlpha0"); + dissolveRampAlphaPropArr[1] = _helper.GetProperty("_DissolveRampAlpha1"); + dissolveRampAlphaPropArr[2] = _helper.GetProperty("_DissolveRampAlpha2"); + _helper.DrawGradient(true, ColorSpace.Gamma, + "Ramp颜色", 6, "_DissolveRampCount", dissolveRampColorPropArr, + dissolveRampAlphaPropArr); + _helper.TextureScaleOffsetProperty("_DissolveRampMap"); + _helper.ColorProperty("Ramp颜色叠加","_DissolveRampColor"); + _helper.DrawWrapMode("溶解RampUV", + W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP, 2); + + }; + if (_helper.ResetTool.IsInitResetData) + { + drawRampTexture(); + drawRampGradient(); + } + else + { + if (!dissolveRampModeProp.hasMixedValue) + { + if (dissolveRampModeProp.floatValue > 0.5f) + { + drawRampTexture(); + } + else + { + drawRampGradient(); + } + } + } + + + _helper.DrawPopUp("溶解Ramp混合模式","_DissolveRampColorBlendMode",dissolveRampBlendModeNames,drawOnValueChangedBlock: + rampColorBend => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (rampColorBend.floatValue > 0.5f) + { + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY,index:1); + } + else + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY,index:1); + } + } + }); + }, drawOnValueChangedBlock: dissolveRampModeProp => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + if (dissolveRampModeProp.floatValue > 0.5f) + { + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags + .FLAG_BIT_PARTICLE_DISSOLVE_RAMP_MAP); + } + else + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags + .FLAG_BIT_PARTICLE_DISSOLVE_RAMP_MAP); + } + } + }); + }); + + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutDissolveMask, 3, GetAnimBoolIndex(3), "溶解遮罩图(过程溶解)", + "_DissolveMask_Toggle", W9ParticleShaderFlags.FLAG_BIT_PARTICLE_DISSOLVE_MASK, drawBlock: + (isToggle) => + { + _helper.DrawPopUp("溶解遮罩模式", "_DissolveMaskMode", dissolveMaskModeNames); + _helper.DrawTexture("溶解遮罩图", "_DissolveMaskMap", drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP, + flagIndex: 2, drawBlock: + texProp => + { + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeDissolveMaskMap, 4, + "溶解遮罩图UV来源", W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP, 0, + texProp); + }); + DrawColorChannelSelect("溶解遮罩图通道选择", + W9ParticleShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP); + bool dissolveMaskStrengthIsSlider = _helper.GetProperty("_DissolveMaskMode").floatValue > 0.5f; + _helper.DrawVector4Component("溶解遮罩强度", "_Dissolve", "z", dissolveMaskStrengthIsSlider,0f,2f); + DrawCustomDataSelect("溶解遮罩图强度自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY, 1); + }); + + DrawPNoiseBlendModeSelect("溶解",W9ParticleShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE,"_DissolvePNoiseBlendOpacity"); + + }); + + MaterialProperty pNoiseToggle = _helper.GetProperty("_ProgramNoise_Toggle"); + if (pNoiseToggle.hasMixedValue) + { + _pNoiseEnabled = -1; + } + else + { + _pNoiseEnabled = pNoiseToggle.floatValue > 0.5f ? 1 : 0; + } + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutProgramNoise, 3, GetAnimBoolIndex(3), "程序化噪波", + "_ProgramNoise_Toggle", shaderKeyword: "_PROGRAM_NOISE", fontStyle: FontStyle.Bold, + drawBlock: (isToggle) => + { + _helper.DrawToggle("程序化噪波测试颜色","_NB_Debug_PNoise",shaderKeyword:"NB_DEBUG_PNOISE"); + + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeProgramNoise, 4, "程序噪波UV来源", W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE, 0); + _helper.DrawFloat("程序化噪波旋转","_ProgramNoise_Rotate"); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2ProgramNoiseSimple,5,GetAnimBoolIndex(5),"Perlin噪波",propertyName:"_ProgramNoise_Simple_Toggle",flagBitsName:W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE,flagIndex:1,drawBlock: + isToggle => + { + _helper.DrawVector4In2Line("_DissolveVoronoi_Vec", "噪波1缩放", true); + _helper.DrawVector4Component("噪波1速度", "_DissolveVoronoi_Vec2", "z", false); + _helper.DrawVector4In2Line("_DissolveVoronoi_Vec4", "噪波1偏移", true); + DrawCustomDataSelect("噪波1偏移速度X自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X, 2); + DrawCustomDataSelect("噪波1偏移速度Y自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y, 2); + _helper.DrawVector4In2Line("_DissolveVoronoi_Vec3", "噪波1偏移速度", true); + }); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2ProgramNoiseVoronoi, 5, + GetAnimBoolIndex(5), "Voronoi噪波", propertyName: "_ProgramNoise_Voronoi_Toggle", + flagBitsName: W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI, flagIndex: 1, + drawBlock: + isToggle => + { + _helper.DrawVector4In2Line("_DissolveVoronoi_Vec", "噪波2缩放", false); + _helper.DrawVector4Component("噪波2速度", "_DissolveVoronoi_Vec2", "w", false); + _helper.DrawVector4In2Line("_DissolveVoronoi_Vec4", "噪波2偏移", false); + DrawCustomDataSelect("噪波2偏移速度X自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X, 2); + DrawCustomDataSelect("噪波2偏移速度Y自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y, 2); + _helper.DrawVector4In2Line("_DissolveVoronoi_Vec3", "噪波2偏移速度", false); + }); + + if ((_helper.GetProperty("_ProgramNoise_Simple_Toggle").floatValue > 0.5 && + _helper.GetProperty("_ProgramNoise_Voronoi_Toggle").floatValue > 0.5) || + _helper.ResetTool.IsInitResetData) + { + DrawPNoiseBlendModeSelect("两种",W9ParticleShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND,"_ProgramNoiseBaseBlendOpacity"); + } + // _helper.DrawVector4Component("噪波整体和溶解贴图混合系数", "_DissolveVoronoi_Vec2", "y", true); + EditorGUILayout.Space(); + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit2SharedUV,5,GetAnimBoolIndex(5),"公共UV","_SharedUVToggle",shaderKeyword:"_SHARED_UV",fontStyle:FontStyle.Bold,drawBlock: + (isToggle) => + { + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit2SharedUVMode,5,"公共UV来源",W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_SHAREDUV,0); + _helper.TextureScaleOffsetProperty("_SharedUV_ST",true); + // _helper.DrawWrapMode("公共UV",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE2_SHAREDUV,8); + DrawCustomDataSelect("偏移X自定义曲线",W9ParticleShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X,3); + DrawCustomDataSelect("偏移Y自定义曲线",W9ParticleShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y,3); + _helper.DrawVector4In2Line("_SharedUV_Vec","偏移速度",true); + _helper.DrawVector4Component("旋转","_SharedUV_Vec","z",false); + _helper.DrawVector4Component("旋转速度","_SharedUV_Vec","w",false); + // DrawNoiseAffectBlock(() => + // { + // _helper.DrawSlider("公共UV扭曲强度控制", "_SharedUV_Distort_Intensity",rangePropertyName: "sharedUVDistortionIntensityRangeVec"); + // + // }); + + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutFresnel, 3, GetAnimBoolIndex(3), "菲涅尔", + "_fresnelEnabled", W9ParticleShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_ON, isIndentBlock: true, + fontStyle: FontStyle.Bold, + drawBlock: (isToggle) => + { + _helper.DrawToggle("菲涅尔值测试","_NB_Debug_Distort",shaderKeyword:"NB_DEBUG_FRESNEL"); + + Action drawFresnelColorMode = () => + { + // matEditor.ColorProperty(_helper.GetProperty("_FresnelColor"), "菲涅尔颜色"); + _helper.ColorProperty("菲涅尔颜色","_FresnelColor"); + _helper.DrawToggle("菲涅尔颜色受Alpha影响", "_FresnelColorAffectByAlpha", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA); + }; + _helper.DrawPopUp("菲涅尔模式", "_FresnelMode", _fresnelModeNames, drawBlock: + fresnelModeProp => + { + if (_helper.ResetTool.IsInitResetData) + { + drawFresnelColorMode(); + } + else + { + if ((!fresnelModeProp.hasMixedValue) && fresnelModeProp.floatValue.Equals((float)FresnelMode.Color)) + { + drawFresnelColorMode(); + } + } + }, + drawOnValueChangedBlock: fresnelModeProp => + { + FresnelMode fresnelMode = (FresnelMode)fresnelModeProp.floatValue; + for (int i = 0; i < shaderFlags.Count; i++) + { + switch (fresnelMode) + { + case FresnelMode.Color: + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags + .FLAG_BIT_PARTICLE_FRESNEL_FADE_ON); + break; + case FresnelMode.Fade: + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags + .FLAG_BIT_PARTICLE_FRESNEL_FADE_ON); + break; + } + } + }); + _helper.DrawVector4Component("菲涅尔强度", "_FresnelUnit", "z", true); + + + if (mats.Count == 1) + { + FresnelMode fresnelMode = (FresnelMode)mats[0].GetFloat("_FresnelMode"); + + } + + _helper.DrawVector4Component("菲涅尔位置", "_FresnelUnit", "x", true, -1f, 1f); + DrawCustomDataSelect("菲尼尔位置自定义曲线", W9ParticleShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET, + 0); + _helper.DrawVector4Component("菲涅尔范围Pow", "_FresnelUnit", "y", true, 0f, 10f); + _helper.DrawVector4Component("菲涅尔硬度", "_FresnelUnit", "w", true, 0f, 1f); + _helper.DrawToggle("翻转菲涅尔", "_InvertFresnel_Toggle", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON); + _helper.DrawVector4XYZComponet("菲涅尔方向偏移","_FresnelRotation"); + }); + + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutVertexOffset, 3, GetAnimBoolIndex(3), "顶点偏移", + "_VertexOffset_Toggle", W9ParticleShaderFlags.FLAG_BIT_PARTICLE_VERTEX_OFFSET_ON, isIndentBlock: true, + fontStyle: FontStyle.Bold, + drawBlock: isToggle => + { + _helper.DrawToggle("顶点偏移方向测试", "_NB_Debug_VertexOffset", shaderKeyword:"NB_DEBUG_VERTEX_OFFSET"); + _helper.DrawTexture("顶点偏移贴图", "_VertexOffset_Map", drawScaleOffset: true, drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP, flagIndex: 2, + drawBlock: texProp => + { + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeVertexOffsetMap, 4, "顶点偏移贴图UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP, 0, texProp); + }); + DrawCustomDataSelect("顶点扰动X轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X, 1); + DrawCustomDataSelect("顶点扰动Y轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y, 1); + + _helper.DrawVector4In2Line("_VertexOffset_Vec", "顶点偏移动画", true); + _helper.DrawVector4Component("顶点偏移强度", "_VertexOffset_Vec", "z", false); + DrawCustomDataSelect("顶点扰动强度自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY, 1); + _helper.DrawToggle("顶点偏移从零开始", "_VertexOffset_StartFromZero", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO, 1); + _helper.DrawToggle("顶点偏移使用法线方向", "_VertexOffset_NormalDir_Toggle", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR, isIndentBlock: false, + drawBlock: + isToggle => + { + if ((!isToggle.hasMixedValue && isToggle.floatValue < 0.5f)||_helper.ResetTool.IsInitResetData) + { + // matEditor.ShaderProperty(_helper.GetProperty("_VertexOffset_CustomDir"), "顶点偏移本地方向"); + _helper.DrawVector4XYZComponet("顶点偏移本地方向","_VertexOffset_CustomDir"); + } + }); + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit1VertexOffsetMask, 4, GetAnimBoolIndex(4), + "顶点偏移遮罩", "_VertexOffset_Mask_Toggle", + W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_VERTEXOFFSET_MASKMAP, 1, + drawBlock: isMaskToggle => + { + _helper.DrawTexture("顶点偏移遮罩图", "_VertexOffset_MaskMap", drawScaleOffset: true, + drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP, + flagIndex: 2, + drawBlock: texProp => + { + DrawUVModeSelect(W9ParticleShaderFlags.foldOutBit1UVModeVertexOffsetMaskMap, 4, + "顶点偏移遮罩图UV来源", + W9ParticleShaderFlags.FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP, 0, texProp); + }); + DrawCustomDataSelect("顶点扰动遮罩X轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X, 3); + DrawCustomDataSelect("顶点扰动遮罩Y轴偏移自定义曲线", + W9ParticleShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y, 3); + _helper.DrawVector4In2Line("_VertexOffset_MaskMap_Vec", "顶点偏移遮罩动画", true); + _helper.DrawVector4Component("顶点偏移遮罩强度", "_VertexOffset_MaskMap_Vec", "z", true); + }); + }); + DrawVATOptions(); + + + + + + if (_uiEffectEnabled == 0) + { + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutDepthOutline, 3, GetAnimBoolIndex(3), "深度描边", + "_DepthOutline_Toggle", + flagBitsName: W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_DEPTH_OUTLINE, fontStyle: FontStyle.Bold, + flagIndex: 1, isIndentBlock: true, + drawBlock: (isToggle) => + { + _helper.ColorProperty("深度描边颜色","_DepthOutline_Color"); + _helper.DrawVector4In2Line("_DepthOutline_Vec", "深度描边距离", true); + }); + + _helper.DrawToggle("深度贴花", "_DepthDecal_Toggle", shaderKeyword: "_DEPTH_DECAL", + fontStyle: FontStyle.Bold, + drawEndChangeCheck: (isToggle) => + { + if (!isToggle.hasMixedValue) + { + for (int i = 0; i < mats.Count; i++) + { + if(_helper.ResetTool.IsInitResetData) break;//避免初始化时重设 + if (isToggle.floatValue > 0.5f) + { + StencilTestHelper.SetMaterialStencil(mats[i], "ParticleBaseDecal", + _stencilValuesConfig, out int ignore); + mats[i].SetFloat(_isCustomedStencilPropID, 1f); + mats[i].SetFloat("_Cull", (float)RenderFace.Back); + mats[i].SetFloat("_ZTest", (float)CompareFunction.GreaterEqual); + } + else + { + StencilTestHelper.SetMaterialStencil(mats[i], _defaultStencilKey, + _stencilValuesConfig, out int ignore); + mats[i].SetFloat(_isCustomedStencilPropID, 0f); + mats[i].SetFloat("_Cull", (float)RenderFace.Front); + mats[i].SetFloat("_ZTest", (float)CompareFunction.LessEqual); + } + } + + } + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutParallexMapping, 3, GetAnimBoolIndex(3), "遮蔽视差", + "_ParallaxMapping_Toggle", shaderKeyword: "_PARALLAX_MAPPING", + isIndentBlock: true, fontStyle: FontStyle.Bold, + drawBlock: isTogggle => + { + _helper.DrawTexture("视差贴图", "_ParallaxMapping_Map", drawWrapMode: true, + wrapModeFlagBitsName: W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP, + flagIndex: 2); + _helper.DrawSlider("视差", "_ParallaxMapping_Intensity", rangePropertyName:"_ParallaxMapping_IntensityRangeVec"); + + Action OnPomLayerCountChange = (f, isMixedValue) => + { + int shaderID = Shader.PropertyToID("_ParallaxMapping_Vec"); + for (int i = 0; i < mats.Count; i++) + { + Vector4 vecValue = mats[i].GetVector(shaderID); + if (vecValue.y < vecValue.x + 1) + { + vecValue.y = vecValue.x + 1; + } + + mats[i].SetVector(shaderID, vecValue); + } + }; + + _helper.DrawVector4Component("遮蔽视差最小层数", "_ParallaxMapping_Vec", "x", true, 0f, 100f, + drawEndChangeCheckBlock: OnPomLayerCountChange); + _helper.DrawVector4Component("遮蔽视差最大层数", "_ParallaxMapping_Vec", "y", true, 0f, 100f, + drawEndChangeCheckBlock: OnPomLayerCountChange, + drawBlock: (f, hasMixedValue) => + { + if (!hasMixedValue && f >= 20f) + { + EditorGUILayout.HelpBox("遮蔽视差层数过高将影响性能", MessageType.Warning); + } + }); + }); + + Action SetPortal = (mat) => + { + StencilTestHelper.SetMaterialStencil(mat, "ParticalBasePortal", _stencilValuesConfig, + out int Ignore); + mat.SetFloat(_isCustomedStencilPropID, 1f); + }; + + Action SetPortalMask = (mat) => + { + StencilTestHelper.SetMaterialStencil(mat, "ParticalBasePortalMask", _stencilValuesConfig, + out int Ignore); + if (mat.GetFloat("_TransparentMode") == (float)TransparentMode.Transparent) + { + mat.SetFloat("_TransparentMode", (float)TransparentMode.CutOff); + } + + mat.SetFloat("_ZTest", (float)CompareFunction.LessEqual); + mat.SetFloat("_ForceZWriteToggle",2); + }; + Action RestPortal = (mat) => + { + StencilTestHelper.SetMaterialStencil(mat, _defaultStencilKey, + _stencilValuesConfig, out int ignore); + mat.SetFloat(_isCustomedStencilPropID, 0f); + mat.SetFloat("_TransparentMode", (float)TransparentMode.Transparent); + mat.SetFloat("_ZTest", (float)CompareFunction.LessEqual); + mat.SetFloat("_ForceZWriteToggle", 0f); + }; + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit1Portal, 4, GetAnimBoolIndex(4), "模板视差", + "_Portal_Toggle", fontStyle: FontStyle.Bold, + drawBlock: isPortalToggle => + { + _helper.DrawToggle("模板视差蒙版", "_Portal_MaskToggle", drawEndChangeCheck: isPortalMaskToggle => + { + if (!isPortalMaskToggle.hasMixedValue) + { + + for (int i = 0; i < mats.Count; i++) + { + + if (isPortalMaskToggle.floatValue > 0.5f) + { + SetPortalMask(mats[i]); + } + else if(isPortalToggle.floatValue >0.5f) + { + SetPortal(mats[i]); + } + else + { + if(_helper.ResetTool.IsInitResetData) continue;//避免初始化时重设 + RestPortal(mats[i]); + } + + } + } + }); + }, drawEndChangeCheck: (isPortalToggle) => + { + + for (int i = 0; i < mats.Count; i++) + { + if (isPortalToggle.floatValue > 0.5f) + { + if (mats[i].GetFloat("_Portal_MaskToggle") < 0.5f) + { + SetPortal(mats[i]); + } + else + { + SetPortalMask(mats[i]); + } + } + else + { + if(_helper.ResetTool.IsInitResetData )continue;//避免初始化时重设 + RestPortal(mats[i]); + } + } + }); + } + + //粒子序列帧融帧的逻辑,是将UV0为第一格,UV1234推到第二格,中间用AnimBlend融合)。所以多UV是必然和这个矛盾的。 + _helper.DrawToggle("序列帧融帧(丝滑)", "_FlipbookBlending", shaderKeyword: "_FLIPBOOKBLENDING_ON", + fontStyle: FontStyle.Bold, drawBlock: (isToggle) => + { + if (!isToggle.hasMixedValue && isToggle.floatValue > 0.5f) + { + if (_meshSourceMode == MeshSourceMode.Particle) + { + if (shaderFlags[0].CheckIsUVModeOn(UVMode.SpecialUVChannel)) + { + EditorGUILayout.HelpBox("序列帧融帧和特殊UV通道同时开启,粒子序列帧应该影响UV0和UV1两个通道,特殊通道只能使用UV3(原始UV)", + MessageType.Warning); + } + else + { + EditorGUILayout.HelpBox("AnimationSheet的AffectUVChannel需要有UV0和UV1", + MessageType.Info); + } + } + else if (_meshSourceMode == MeshSourceMode.Mesh) + { + EditorGUILayout.HelpBox("需要添加AnimationSheetHelper脚本", MessageType.Info); + } + } + }, + drawEndChangeCheck: SyncFlipbookVatExclusion); + + } + + public void DrawTaOptions() + { + if (_uiEffectEnabled == 0) + { + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit1ZOffset, 4, GetAnimBoolIndex(4), "深度偏移", + "_ZOffset_Toggle", fontStyle: FontStyle.Bold, drawBlock: + (isToggle) => + { + + matEditor.ShaderProperty(_helper.GetProperty("_offsetFactor"), "OffsetFactor"); + matEditor.ShaderProperty(_helper.GetProperty("_offsetUnits"), "Offset单位"); + }, + drawEndChangeCheck: (isToggle) => + { + if (!isToggle.hasMixedValue && isToggle.floatValue < 0.5f) + { + for (int i = 0; i < mats.Count; i++) + { + mats[i].SetFloat("_offsetFactor", 0f); + mats[i].SetFloat("_offsetUnits", 0f); + } + } + }); + } + + + _helper.DrawRenderQueue(_helper.GetProperty("_QueueBias")); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBit1CustomStencilTest, 4, GetAnimBoolIndex(4), + "模板手动调试开关", "_CustomStencilTest", + drawBlock: isToggle => + { + bool hasMixedKeyValue = false; + int stencilKeyIndexID = Shader.PropertyToID("_StencilKeyIndex"); + string originKey = ""; + for (int i = 0; i < mats.Count; i++) + { + string key = _stencilValuesConfig.GetKeyByIndex(mats[i].GetInt(stencilKeyIndexID)); + if (i == 0) + { + originKey = key; + } + else + { + if (originKey != key) hasMixedKeyValue = true; + } + + hasMixedKeyValue = false; + } + + EditorGUI.showMixedValue = hasMixedKeyValue; + EditorGUI.BeginDisabledGroup(true); + EditorGUILayout.TextField("当前Config:", originKey); + EditorGUI.EndDisabledGroup(); + EditorGUI.showMixedValue = false; + + matEditor.ShaderProperty(_helper.GetProperty("_Stencil"), "模板值"); + matEditor.ShaderProperty(_helper.GetProperty("_StencilComp"), "模板比较方式"); + matEditor.ShaderProperty(_helper.GetProperty("_StencilOp"), "模板处理方式"); + + }, + drawEndChangeCheck: isToggle => + { + if (!isToggle.hasMixedValue) + { + for (int i = 0; i < mats.Count; i++) + { + if (isToggle.floatValue > 0.5f) + { + mats[i].SetFloat(_isCustomedStencilPropID, 1f); + } + else + { + StencilTestHelper.SetMaterialStencil(mats[i], _defaultStencilKey, _stencilValuesConfig, + out int ignore); + } + + } + } + }); + + + if (mats.Count == 1) + { + _helper.DrawFoldOut(W9ParticleShaderFlags.foldOutBit1ShaderKeyword, 4, GetAnimBoolIndex(4), + "已开启Keyword:", drawBlock: + () => + { + List shaderKeywords = new List(); + foreach (var localKeyword in mats[0].enabledKeywords) + { + shaderKeywords.Add(localKeyword.name); + } + + if (shaderKeywords != null && shaderKeywords.Count > 0) + { + float height = EditorGUIUtility.singleLineHeight * shaderKeywords.Count; + Rect labelRect = EditorGUILayout.GetControlRect(false, height); + string label = ""; + for (int i = 0; i < shaderKeywords.Count; i++) + { + label += shaderKeywords[i]; + label += "\n"; + } + + EditorGUI.LabelField(labelRect, label); + } + + }); + } + } + + void DrawNoiseAffectBlock(Action drawBlock) + { + + EditorGUI.BeginDisabledGroup(_noiseEnabled == 0); + EditorGUI.showMixedValue = _noiseEnabled < 0; + drawBlock(); + EditorGUI.showMixedValue = false; + EditorGUI.EndDisabledGroup(); + } + + public string[] blendModeNames = + { + "透明度混合AlphaBlend", + "预乘PreMultiply", + "叠加Additive", + "正片叠底Multiply" + }; + + public enum BlendMode + { + Alpha, // Old school alpha-blending mode, fresnel does not affect amount of transparency + Premultiply, // Physically plausible transparency mode, implemented as alpha pre-multiply + Additive, + Multiply, + Opaque + } + + public enum TimeMode + { + Default, + UnScaleTime, + ScriptableTime + } + + public enum RenderFace + { + Front = 2, + Back = 1, + Both = 0 + } + + public enum FresnelMode + { + Color = 0, + Fade = 1, + UnkownOrMixed = -1 + } + + private string[] _fresnelModeNames = + { + "颜色|边缘光", + "半透明|渐隐" + }; + + private string[] _maskMapModeNames = + { + "遮罩贴图", + "渐变控件" + }; + + private string[] _ForceZWriteToggleNames = + { + "默认", + "强制开启", + "强制关闭" + }; + + + public enum FxLightMode + { + UnLit, + BlinnPhong, + HalfLambert, + PBR, + SixWay, + UnKnownOrMixedValue = -1 + } + private string[] _fxLightModeNames = + { + "默认无光(Unlit)", + "简单光照(BlinnPhong)", + "简单光照通透(HalfLambert)", + "高级光照(PBR)", + "六路光照(SixWay)" + }; + + public string[] transparentModeNames = + { + "不透明Opaque", + "半透明Transparent", + "不透明裁剪CutOff" + }; + + public enum TransparentMode + { + Opaque = 0, + Transparent = 1, + CutOff = 2, + UnKnowOrMixed = -1 + } + + private string[] matCapBlendModeNames = + { + "相加Add", + "相乘Multiply", + }; + + private string[] dissolveRampBlendModeNames = + { + "线性差值Lerp", + "相乘Multiply", + }; + + private string[] colorBlendAlphaMode = new[] + { + "颜色渐变强度", + "遮罩(乘以主贴图Alpha)" + }; + + private string[] rampColorSourceMode = + { + "UV", + "映射贴图" + }; + + private string[] dissolveRampSourceMode = + { + "渐变控件", + "Ramp贴图" + }; + + private string[] dissolveMaskModeNames = + { + "过程溶解", + "溶解遮罩" + }; + + private string[] rampColorBlendMode = + { + "相乘Multiply", + "相加Add" + }; + + public enum ScreenDistortMode + { + None = 0, + DeferredDistort = 1, + CameraOpaqueDistort = 2, + Mixed = -1 + } + + private string[] screenDistortModeNames = + { + "不扰动屏幕", + "全部扰动(后处理扰动)", + "仅影响场景(半透明前扰动)" + }; + + private string[] distortModeNames = + { + "扰动贴图", + "折射" + }; + + internal enum VATMode + { + Houdini = 0, + Tyflow = 1 + } + + private readonly string[] _vatModeNames = + { + "Houdini", + "Tyflow" + }; + + private static bool IsUIMeshSourceMode(MeshSourceMode mode) + { + return mode == MeshSourceMode.UIEffectRawImage || + mode == MeshSourceMode.UIEffectSprite || + mode == MeshSourceMode.UIEffectBaseMap || + mode == MeshSourceMode.UIParticle; + } + + void DoAfterDraw() + { + // Debug.Log(mats[0].name + " MaterialEditorDoAfterDraw!"); + for (int i = 0; i < mats.Count; i++) + { + + switch (_meshSourceMode) + { + case MeshSourceMode.Particle: + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM, index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UV_FROM_MESH, index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UIEFFECT_ON, index: 0); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE, + index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE, + index: 1); + + //如果是粒子系统,则不需要走AnimationSheetHelper + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER); + break; + case MeshSourceMode.Mesh: + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM, + index: 1); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UV_FROM_MESH, index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UIEFFECT_ON, index: 0); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE, + index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE, + index: 1); + break; + case MeshSourceMode.UIEffectRawImage: + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM, + index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UV_FROM_MESH, index: 1); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UIEFFECT_ON, index: 0); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE, + index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE, + index: 1); + break; + case MeshSourceMode.UIEffectSprite: + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM, + index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UV_FROM_MESH, index: 1); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UIEFFECT_ON, index: 0); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE, + index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE, + index: 1); + break; + case MeshSourceMode.UIEffectBaseMap: + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM, + index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UV_FROM_MESH, index: 1); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UIEFFECT_ON, index: 0); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE, + index: 1); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE, + index: 1); + break; + } + + + if (_meshSourceModeIsParticle > 0.5f) + { + + if (shaderFlags[i].IsCustomData1On()) + { + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA1_ON); + } + else + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA1_ON); + } + + if (shaderFlags[i].IsCustomData2On()) + { + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA2_ON); + } + else + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA2_ON); + } + + } + + switch (_fxLightMode) + { + case FxLightMode.UnLit: + mats[i].EnableKeyword("_FX_LIGHT_MODE_UNLIT"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_BLINN_PHONG"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_HALF_LAMBERT"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_PBR"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_SIX_WAY"); + mats[i].DisableKeyword("EVALUATE_SH_VERTEX"); + break; + case FxLightMode.BlinnPhong: + mats[i].DisableKeyword("_FX_LIGHT_MODE_UNLIT"); + mats[i].EnableKeyword("_FX_LIGHT_MODE_BLINN_PHONG"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_HALF_LAMBERT"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_PBR"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_SIX_WAY"); + mats[i].DisableKeyword("EVALUATE_SH_VERTEX"); + break; + case FxLightMode.HalfLambert: + mats[i].DisableKeyword("_FX_LIGHT_MODE_UNLIT"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_BLINN_PHONG"); + mats[i].EnableKeyword("_FX_LIGHT_MODE_HALF_LAMBERT"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_PBR"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_SIX_WAY"); + mats[i].DisableKeyword("EVALUATE_SH_VERTEX"); + break; + + case FxLightMode.PBR: + mats[i].DisableKeyword("_FX_LIGHT_MODE_UNLIT"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_BLINN_PHONG"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_HALF_LAMBERT"); + mats[i].EnableKeyword("_FX_LIGHT_MODE_PBR"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_SIX_WAY"); + mats[i].DisableKeyword("EVALUATE_SH_VERTEX"); + break; + case FxLightMode.SixWay: + mats[i].DisableKeyword("_FX_LIGHT_MODE_UNLIT"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_BLINN_PHONG"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_HALF_LAMBERT"); + mats[i].DisableKeyword("_FX_LIGHT_MODE_PBR"); + mats[i].EnableKeyword("_FX_LIGHT_MODE_SIX_WAY"); + mats[i].EnableKeyword("EVALUATE_SH_VERTEX");//强制六面体使用顶点SH。 + break; + } + + if (!shaderFlags[i].CheckIsUVModeOn(UVMode.SpecialUVChannel)) + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1, index: 1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1); + } + + if (!shaderFlags[i].CheckIsUVModeOn(UVMode.Cylinder)) + { + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE, index: 1); + } + + + TransparentMode transparentMode = (TransparentMode)mats[i].GetFloat("_TransparentMode"); + if (transparentMode != TransparentMode.Transparent) + { + mats[i].SetFloat("_TransparentShadowDitherToggle", 0); + } + int queueBias = (int)mats[i].GetFloat("_QueueBias"); + switch (transparentMode) + { + case TransparentMode.Opaque: + mats[i].SetInt("_ZWrite", (int)1); + mats[i].renderQueue = 2100 + queueBias; //3D粒子永远最前显示 + mats[i].SetInt("_Blend", (int)BlendMode.Opaque); + break; + case TransparentMode.Transparent: + mats[i].SetInt("_ZWrite", (int)0); + int defaultQueue = 3100; + if (_uiEffectEnabled == 1) + { + defaultQueue = 3000; + } + + mats[i].renderQueue = defaultQueue + queueBias; //3D粒子永远最前显示 + + BlendMode bm = (BlendMode)mats[i].GetFloat("_Blend"); + if (bm == BlendMode.Opaque) + { + mats[i].SetFloat("_Blend", (float)BlendMode.Alpha); //如果设置错误则强制设置。 + } + + break; + case TransparentMode.CutOff: + mats[i].SetInt("_ZWrite", (int)1); + mats[i].renderQueue = 2450 + queueBias; //3D粒子永远最前显示 + mats[i].SetInt("_Blend", (int)BlendMode.Opaque); + break; + } + + float forceZWriteToggle = mats[i].GetFloat("_ForceZWriteToggle"); + if ( forceZWriteToggle > 0.5f&& forceZWriteToggle<1.5f) + { + mats[i].SetInt("_ZWrite", (int)1); + } + else if(forceZWriteToggle > 1.5f) + { + mats[i].SetInt("_ZWrite", (int)0); + } + + if (_transparentMode == TransparentMode.CutOff) + { + mats[i].EnableKeyword("_ALPHATEST_ON"); + } + else + { + mats[i].DisableKeyword("_ALPHATEST_ON"); + } + + MeshSourceMode materialMeshSourceMode = (MeshSourceMode)mats[i].GetFloat("_MeshSourceMode"); + bool isUIMode = IsUIMeshSourceMode(materialMeshSourceMode); + bool depthOnlyEnabled = !isUIMode && mats[i].GetInt("_ZWrite") == 1; + bool shadowCasterEnabled = !isUIMode && + mats[i].GetFloat("_AffectsShadows") > 0.5f && + (transparentMode == TransparentMode.Opaque || + transparentMode == TransparentMode.CutOff || + transparentMode == TransparentMode.Transparent); + + mats[i].SetShaderPassEnabled("DepthOnly", depthOnlyEnabled); + mats[i].SetShaderPassEnabled("ShadowCaster", shadowCasterEnabled); + + + + // blendMode + BlendMode blendMode = (BlendMode)mats[i].GetFloat("_Blend"); + + switch (blendMode) + { + case BlendMode.Alpha: + mats[i].SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); + mats[i].SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + mats[i].DisableKeyword("_ALPHAPREMULTIPLY_ON"); + mats[i].DisableKeyword("_ALPHAMODULATE_ON"); + break; + case BlendMode.Premultiply: + mats[i].SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + mats[i].SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + mats[i].EnableKeyword("_ALPHAPREMULTIPLY_ON"); + mats[i].DisableKeyword("_ALPHAMODULATE_ON"); + break; + case BlendMode.Additive: + mats[i].SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + mats[i].SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + mats[i].EnableKeyword("_ALPHAPREMULTIPLY_ON"); + mats[i].DisableKeyword("_ALPHAMODULATE_ON"); + break; + case BlendMode.Multiply: + mats[i].SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor); + mats[i].SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + mats[i].DisableKeyword("_ALPHAPREMULTIPLY_ON"); + mats[i].EnableKeyword("_ALPHAMODULATE_ON"); + break; + case BlendMode.Opaque: + mats[i].SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + mats[i].SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + mats[i].DisableKeyword("_ALPHAPREMULTIPLY_ON"); + break; + } + + TimeMode timeMode = (TimeMode)mats[i].GetFloat("_TimeMode"); + + switch (timeMode) + { + case TimeMode.Default: + // setMaterialFlags(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UNSCALETIME_ON, false); + // setMaterialFlags(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON, false); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UNSCALETIME_ON); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON); + break; + case TimeMode.UnScaleTime: + // setMaterialFlags(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UNSCALETIME_ON, true); + // setMaterialFlags(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON, false); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UNSCALETIME_ON); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON); + break; + case TimeMode.ScriptableTime: + // setMaterialFlags(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UNSCALETIME_ON, false); + // setMaterialFlags(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON, true); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UNSCALETIME_ON); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON); + break; + } + + SyncVatKeywords(mats[i]); + } + } + + private void SyncVatKeywords(Material material) + { + bool vatEnabled = material.GetFloat("_VAT_Toggle") > 0.5f; + if (!vatEnabled) + { + ClearVatKeywords(material); + return; + } + + DisableFlipbook(material); + material.EnableKeyword("_VAT"); + VATMode mode = GetVatMode(material); + switch (mode) + { + case VATMode.Tyflow: + material.DisableKeyword("_VAT_HOUDINI"); + material.EnableKeyword("_VAT_TYFLOW"); + ParticleBaseHoudiniVATGUI.ClearKeywords(material); + ParticleBaseTyflowVATGUI.SyncKeywords(material); + break; + default: + material.EnableKeyword("_VAT_HOUDINI"); + material.DisableKeyword("_VAT_TYFLOW"); + ParticleBaseHoudiniVATGUI.SyncKeywords(material); + ParticleBaseTyflowVATGUI.ClearKeywords(material); + break; + } + } + + private void SyncFlipbookVatExclusion(MaterialProperty flipbookProperty) + { + if (flipbookProperty.hasMixedValue || flipbookProperty.floatValue <= 0.5f) + { + return; + } + + foreach (Material mat in mats) + { + DisableVat(mat); + } + } + + private static void DisableVat(Material material) + { + if (material == null) + { + return; + } + + if (material.HasProperty("_VAT_Toggle")) + { + material.SetFloat("_VAT_Toggle", 0.0f); + } + + ClearVatKeywords(material); + } + + private static void ClearVatKeywords(Material material) + { + if (material == null) + { + return; + } + + material.DisableKeyword("_VAT"); + material.DisableKeyword("_VAT_HOUDINI"); + material.DisableKeyword("_VAT_TYFLOW"); + ParticleBaseHoudiniVATGUI.ClearKeywords(material); + ParticleBaseTyflowVATGUI.ClearKeywords(material); + } + + private static void DisableFlipbook(Material material) + { + if (material == null) + { + return; + } + + if (material.HasProperty("_FlipbookBlending")) + { + material.SetFloat("_FlipbookBlending", 0.0f); + } + + material.DisableKeyword("_FLIPBOOKBLENDING_ON"); + } + + private VATMode GetVatMode(Material material) + { + int mode = Mathf.RoundToInt(material.GetFloat("_VATMode")); + if (mode < (int)VATMode.Houdini || mode > (int)VATMode.Tyflow) + { + material.SetFloat("_VATMode", (float)VATMode.Houdini); + return VATMode.Houdini; + } + + return (VATMode)mode; + } + + private void DrawVATOptions() + { + _helper.DrawToggleFoldOut( + W9ParticleShaderFlags.foldOutBit2VAT, + 5, + GetAnimBoolIndex(5), + "VAT顶点动画图", + "_VAT_Toggle", + shaderKeyword: "_VAT", + fontStyle: FontStyle.Bold, + drawBlock: isToggle => + { + DrawVatModeSelector(); + + if (!TryGetSelectedVatMode(out VATMode mode)) + { + return; + } + + switch (mode) + { + case VATMode.Tyflow: + _tyflowVatGui.Draw(); + break; + default: + _houdiniVatGui.Draw(); + break; + } + }, + drawEndChangeCheck: isToggle => + { + if (isToggle.hasMixedValue) + { + return; + } + + foreach (Material mat in mats) + { + if (isToggle.floatValue > 0.5f) + { + GetVatMode(mat); + } + + SyncVatKeywords(mat); + } + }); + } + + private void DrawVatModeSelector() + { + _helper.DrawPopUp( + "VAT模式", + "_VATMode", + _vatModeNames, + drawOnValueChangedBlock: modeProp => + { + if (modeProp.hasMixedValue) + { + return; + } + + foreach (Material mat in mats) + { + mat.SetFloat("_VATMode", modeProp.floatValue); + SyncVatKeywords(mat); + } + }); + } + + private bool TryGetSelectedVatMode(out VATMode mode) + { + MaterialProperty vatModeProperty = _helper.GetProperty("_VATMode"); + if (vatModeProperty == null) + { + mode = VATMode.Houdini; + return false; + } + + if (vatModeProperty.hasMixedValue) + { + mode = VATMode.Houdini; + return false; + } + + int rawMode = Mathf.RoundToInt(vatModeProperty.floatValue); + if (rawMode < (int)VATMode.Houdini || rawMode > (int)VATMode.Tyflow) + { + mode = VATMode.Houdini; + return true; + } + + mode = (VATMode)rawMode; + return true; + } + + private void AppendVatRequiredVertexStreams( + Material material, + List streams, + List streamList) + { + if (material.GetFloat("_VAT_Toggle") <= 0.5f) + { + return; + } + + switch (GetVatMode(material)) + { + case VATMode.Tyflow: + ParticleBaseTyflowVATGUI.AppendRequiredVertexStreams(material, streams, streamList); + break; + default: + ParticleBaseHoudiniVATGUI.AppendRequiredVertexStreams(material, streams, streamList); + break; + } + } + + public static GUIContent VertexStreams = new GUIContent("顶点流统计", + "The vertex streams needed for this Material to function properly."); + + public static string streamPositionText = "Position (POSITION.xyz)"; + public static string streamNormalText = "Normal (NORMAL.xyz)"; + public static string streamColorText = "Color (COLOR.xyzw)"; + public static string streamUVText = "UV (TEXCOORD0.xy)"; + public static string streamUV3Text = "UV3 (TEXCOORD0.zw)"; + public static string streamUV2Text = "UV2 (TEXCOORD0.zw)"; + public static string streamUV2AndAnimBlendText = "UV2 (TEXCOORD3.zw)"; + public static string streamUV3AndAnimBlendText = "UV3 (TEXCOORD3.zw)"; + public static string streamAnimBlendText = "AnimBlend (TEXCOORD3.x)"; + public static string streamTangentText = "Tangent (TANGENT.xyzw)"; + public static string streamCustom1Text = "Custom1.xyzw(TEXCOORD1.xyzw)"; + public static string streamCustom2Text = "Custom2.xyzw(TEXCOORD2.xyzw)"; + + + public static GUIContent streamApplyToAllSystemsText = new GUIContent("使粒子与材质顶点流相同", + "Apply the vertex stream layout to all Particle Systems using this material"); + + public static string undoApplyCustomVertexStreams = L10n.Tr("Apply custom vertex streams from material"); + + List m_ParticleRenderersUsingThisMaterial = new List(); + List m_RenderersUsingThisMaterial = new List(); + + private bool checkIsParicleSystem = false; + void CacheRenderersUsingThisMaterial(Material material, int matID) + { + checkIsParicleSystem = false; + m_ParticleRenderersUsingThisMaterial.Clear(); + m_RenderersUsingThisMaterial.Clear(); + Renderer[] renderers = UnityObjectFindCompat.FindAll(); + m_RenderersUsingThisMaterial.Clear(); + foreach (Renderer renderer in renderers) + { + if (renderer is ParticleSystemRenderer) + { + ParticleSystemRenderer psr = renderer as ParticleSystemRenderer; + if (psr.sharedMaterial == material || psr.trailMaterial == material) + { + checkIsParicleSystem = true; + shaderFlags[matID].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER,index:1);//如果是粒子系统用,就主动关掉Helper的类型。 + m_ParticleRenderersUsingThisMaterial.Add(psr); + } + } + + foreach (var mat in renderer.sharedMaterials) + { + if (mat == material) + { + m_RenderersUsingThisMaterial.Add(renderer); + break; + } + } + + } + _helper.InitRenderers(m_RenderersUsingThisMaterial); + } + + //雨轩:UnityEditorInternal命名空间下提供 一个类ReorderableList可以实现通过拖曳来达到列表元素的重新排序。 + private static ReorderableList vertexStreamList; + //构建粒子系统顶点流界面 + public void DoVertexStreamsArea(Material material, List renderers, + int matID, bool useLighting = false) + { + EditorGUILayout.Space(); + + // bool useFlipbookBlending = (material.GetFloat("_FlipbookBlending") > 0.0f); + bool useFlipbookBlending = material.IsKeywordEnabled("_FLIPBOOKBLENDING_ON"); + bool useSpecialUVChannel = shaderFlags[matID].CheckIsUVModeOn(UVMode.SpecialUVChannel); + bool isUseUV3ForSpecialUV = + shaderFlags[matID].CheckFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index:1); + // bool CustomDataEnabled = (material.GetFloat("_CustomData") > 0.0f); + bool isCustomData1 = shaderFlags[matID].CheckFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA1_ON); + bool isCustomData2 = shaderFlags[matID].CheckFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA2_ON); + + + // Build the list of expected vertex streams + List streams = new List(); + List streamList = new List(); + + streams.Add(ParticleSystemVertexStream.Position); //必然会传递有顶点位置信息 + streamList.Add(streamPositionText); //记录顶点位置信息,给GUI面板用 + + bool needTangent = false; + bool needNormal = false; + + needNormal = (material.GetFloat("_VertexOffset_NormalDir_Toggle") > 0.5f); + + //如果有灯光,必有法线信息。如果有法线贴图,必有顶点切线法线信息。 + //菲涅尔效果需要用到法线内容。 + if (material.GetFloat("_fresnelEnabled") > 0.5f) + { + needNormal = true; + needTangent = true; + } + + if (material.GetFloat("_ParallaxMapping_Toggle") > 0.5f) + { + needNormal = true; + needTangent = true; + } + + if (_fxLightMode != FxLightMode.UnLit || material.GetFloat("_BumpMapToggle") > 0.5f) + { + needNormal = true; + needTangent = true; + } + + bool useUV3AsMainUV = shaderFlags[matID].CheckFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_USETEXCOORD2); + + if (needTangent) + { + streams.Add(ParticleSystemVertexStream.Tangent); + streamList.Add(streamTangentText); + } + + if (needNormal) + { + streams.Add(ParticleSystemVertexStream.Normal); + streamList.Add(streamNormalText); + } + + //粒子着色器,必有顶点颜色信息。 + streams.Add(ParticleSystemVertexStream.Color); + streamList.Add(streamColorText); + + //TEXCOORD0填充 + //必有顶点第一套UV信息。 + streams.Add(ParticleSystemVertexStream.UV); + streamList.Add(streamUVText); + //在做动画序列帧时,需要:TEXCOORD1(xy为正常uv,zw为Blend用的第二套uv),:TEXCOORD2(x为Blend混合值) + if (useFlipbookBlending && useSpecialUVChannel) + { + streams.Add(ParticleSystemVertexStream.UV2); + streamList.Add(streamUV2Text); + } + else if (useSpecialUVChannel & !useFlipbookBlending) + { + + if (isUseUV3ForSpecialUV) + { + streams.Add(ParticleSystemVertexStream.UV3); + streamList.Add(streamUV3Text); + } + else + { + streams.Add(ParticleSystemVertexStream.UV2); + streamList.Add(streamUV2Text); + } + + } + else if (useFlipbookBlending & !useSpecialUVChannel) + { + if (!streams.Contains(ParticleSystemVertexStream.UV2)) + { + streams.Add(ParticleSystemVertexStream.UV2); + streamList.Add(streamUV2Text); + } + } + else if(isCustomData1 || isCustomData2) + { + streams.Add(ParticleSystemVertexStream.UV2); + streamList.Add(streamUV2Text); + } + + + //填充TEXCOORD1 + bool isFillSkipUV2 = false;//因为如果要使用UV3,粒子系统必须填充UV2才能激活 + if (isCustomData1 || isCustomData2 || useFlipbookBlending) + { + streams.Add(ParticleSystemVertexStream.Custom1XYZW); + streamList.Add(streamCustom1Text); + } + else if(useSpecialUVChannel & isUseUV3ForSpecialUV) + { + streams.Add(ParticleSystemVertexStream.UV2); + streamList.Add("TEXCOORD1.xy"); + isFillSkipUV2 = true; + } + + //填充TEXCOORD2 + if (isCustomData2 || useFlipbookBlending) + { + streams.Add(ParticleSystemVertexStream.Custom2XYZW); + streamList.Add(streamCustom2Text); + } + else if(useSpecialUVChannel & isUseUV3ForSpecialUV & !isFillSkipUV2) + { + streams.Add(ParticleSystemVertexStream.UV2); + streamList.Add("TEXCOORD2.xy"); + isFillSkipUV2 = true; + } + + //填充TEXCOORD3 + if (useFlipbookBlending) + { + streams.Add(ParticleSystemVertexStream.AnimBlend); + streamList.Add(streamAnimBlendText); + if (useSpecialUVChannel) + { + if (isUseUV3ForSpecialUV) + { + streams.Add(ParticleSystemVertexStream.UV3); + streamList.Add(streamUV3AndAnimBlendText); + } + } + } + else if(useSpecialUVChannel & isUseUV3ForSpecialUV & !isFillSkipUV2) + { + streams.Add(ParticleSystemVertexStream.UV2); + streamList.Add("TEXCOORD3.xy"); + } + + AppendVatRequiredVertexStreams(material, streams, streamList); + + + //可排序列表绘制。 + //创建一个可排序列表 + vertexStreamList = new ReorderableList(streamList, typeof(string), false, true, false, false); + + //创建表头。ReorderableList下面还有很多回调。可以按需选择。 + vertexStreamList.drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, "Vertex Streams"); }; + + vertexStreamList.DoLayoutList(); //执行表格绘制。 + + // Display a warning if any renderers have incorrect vertex streams + string Warnings = ""; + List rendererStreams = new List(); + foreach (ParticleSystemRenderer renderer in renderers) //每个使用该材质的粒子系统都会进行比较 + { + renderer.GetActiveVertexStreams(rendererStreams); //获得ParticleSystemRenderer的顶点流 + if (!rendererStreams.SequenceEqual(streams)) //重点!是否和我们拼装的顶点流一致。 + Warnings += "-" + renderer.name + "\n"; + } + + // + if (!string.IsNullOrEmpty(Warnings)) + { + //如果有Warning + EditorGUILayout.HelpBox( + "下面的粒子系统Renderer顶点流不正确:\n" + + Warnings, MessageType.Error, true); + // Set the streams on all systems using this materialz + if (GUILayout.Button("使粒子与材质顶点流相同", EditorStyles.miniButton, + GUILayout.ExpandWidth(true))) + { + //做一个撤回记录。 + Undo.RecordObjects(renderers.Where(r => r != null).ToArray(), "Apply custom vertex streams from material"); + + //重点!直接赋值我们拼装好的顶点流。 + foreach (ParticleSystemRenderer renderer in renderers) + { + renderer.SetActiveVertexStreams(streams); + + } + } + } + + //从2022.3.11开始添加这个功能。 + #if UNITY_2022_3_OR_NEWER && !(UNITY_2022_3_0 ||UNITY_2022_3_1||UNITY_2022_3_2||UNITY_2022_3_3||UNITY_2022_3_4||UNITY_2022_3_5||UNITY_2022_3_6||UNITY_2022_3_7||UNITY_2022_3_8||UNITY_2022_3_9||UNITY_2022_3_10) + // Display a warning if any renderers have incorrect vertex streams + string trailWarnings = ""; + List trailRendererStreams = new List(); + foreach (ParticleSystemRenderer renderer in renderers) //每个使用该材质的粒子系统都会进行比较 + { + renderer.GetActiveTrailVertexStreams(trailRendererStreams); //获得ParticleSystemRenderer的顶点流 + if (!trailRendererStreams.SequenceEqual(streams)) //重点!是否和我们拼装的顶点流一致。 + trailWarnings += "-" + renderer.name + "\n"; + } + + if (!string.IsNullOrEmpty(trailWarnings)) + { + //如果有Warning + EditorGUILayout.HelpBox( + "下面的粒子系统Renderer拖尾顶点流不正确:\n" + + trailWarnings, MessageType.Error, true); + // Set the streams on all systems using this material + if (GUILayout.Button("使粒子拖尾与材质顶点流相同", EditorStyles.miniButton, + GUILayout.ExpandWidth(true))) + { + //做一个撤回记录。 + Undo.RecordObjects(renderers.Where(r => r != null).ToArray(), "Apply custom vertex streams from material"); + + //重点!直接赋值我们拼装好的顶点流。 + foreach (ParticleSystemRenderer renderer in renderers) + { + renderer.SetActiveTrailVertexStreams(streams); + } + } + } + #endif + + } + + internal static readonly string[] CustomDataOptions = + { + "**不使用**", + "CustomData1_X", + "CustomData1_Y", + "CustomData1_Z", + "CustomData1_W", + "CustomData2_X", + "CustomData2_Y", + "CustomData2_Z", + "CustomData2_W" + }; + + + bool CustomDataHasMixedValue(int dataBitPos, int dataIndex) + { + W9ParticleShaderFlags.CutomDataComponent + component = W9ParticleShaderFlags.CutomDataComponent.UnKnownOrMixed; + for (int i = 0; i < shaderFlags.Count; i++) + { + W9ParticleShaderFlags.CutomDataComponent curComponent = + shaderFlags[i].GetCustomDataFlag(dataBitPos, dataIndex); + if (i == 0) + { + component = curComponent; + } + else + { + if (component != curComponent) return true; + } + } + + return false; + } + public void DrawCustomDataSelect(string label, int dataBitPos, int dataIndex) + { + // if(!_isUseParticleSystem)return;//只有粒子系统才会处理相关内容。 + // if (mats.Count != 1) return; //仅单选触发 + + if(_meshSourceModeIsParticle <=0 ) return; + (string, string) nameTuple = (label, ""); + //-------------这里需要处理多选情况-------------- + EditorGUI.showMixedValue = CustomDataHasMixedValue(dataBitPos, dataIndex); + W9ParticleShaderFlags.CutomDataComponent component = shaderFlags[0].GetCustomDataFlag(dataBitPos, dataIndex); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + component = (W9ParticleShaderFlags.CutomDataComponent)EditorGUILayout.Popup(new GUIContent(label), (int)component, CustomDataOptions); + EditorGUI.showMixedValue = false; + Action customDataDrawEndChangeCheck = () => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + shaderFlags[i].SetCustomDataFlag(component,dataBitPos,dataIndex); + } + _helper.ResetTool.CheckOnValueChange(nameTuple); + }; + if (EditorGUI.EndChangeCheck()) + { + customDataDrawEndChangeCheck(); + } + _helper.ResetTool.DrawResetModifyButton(new Rect(),nameTuple, + resetCallBack:()=> + { + component = 0; + customDataDrawEndChangeCheck(); + },onValueChangedCallBack:customDataDrawEndChangeCheck, + checkHasModifyOnValueChange: () => shaderFlags[0].GetCustomDataFlag(dataBitPos, dataIndex)!= 0 , + checkHasMixedValueOnValueChange:()=>CustomDataHasMixedValue(dataBitPos, dataIndex)); + EditorGUILayout.EndHorizontal(); + _helper.ResetTool.EndResetModifyButtonScope(); + + } + + + private string[] _uvModeNames = + { + "默认UV通道", + "特殊UV通道", + "极坐标|旋转", + "圆柱无缝", + "主贴图", + "屏幕UV", + "世界坐标", + "局部本地坐标", + "公共UV" + }; + + private string[] _posUVModeNames = + { + "xy平面", + "xz平面", + "yz平面", + }; + + enum SpecialUVChannelMode + { + UV2_Texcoord1, + UV3_Texcoord2 + } + + bool UvModeHasMixedValue(int uvModeBitPos, int uvModeFlagIndex) + { + UVMode uvMode = UVMode.UnknownOrMixed; + for (int i = 0; i < shaderFlags.Count; i++) + { + if (i == 0) + { + uvMode = shaderFlags[i].GetUVMode(uvModeBitPos, uvModeFlagIndex); + } + else + { + if (uvMode != shaderFlags[i].GetUVMode(uvModeBitPos, uvModeFlagIndex)) + { + return true; + } + } + } + return false; + } + public void DrawUVModeSelect(int foldOutFlagBit, int foldOutFlagIndex,string label, int uvModeBitPos, int uvModeFlagIndex,MaterialProperty textureProp = null,bool forceEnable = false) + { + // if(textureProp.hasMixedValue) return; + if(forceEnable) + { + EditorGUI.BeginDisabledGroup(false); + } + else if (textureProp != null) + { + EditorGUI.BeginDisabledGroup(!textureProp.textureValue); + } + else + { + EditorGUI.BeginDisabledGroup(false); + } + bool uvModeHasMixedValue = UvModeHasMixedValue(uvModeBitPos, uvModeFlagIndex); + EditorGUI.showMixedValue = uvModeHasMixedValue; + (string, string) wrapModeNameTuple = (label, ""); + + EditorGUILayout.BeginHorizontal(); + + + Rect rect = EditorGUILayout.GetControlRect(); + var labelRect = new Rect(rect.x , rect.y, rect.width, rect.height); + var popUpRect = _helper.GetRectAfterLabelWidth(rect,true); + + bool isChangeUVMode = false; + EditorGUI.BeginChangeCheck(); + UVMode uvMode = shaderFlags[0].GetUVMode(uvModeBitPos, uvModeFlagIndex); + + Action drawUVModeEndChangeCheck = () => + { + isChangeUVMode = true; + for (int i = 0; i < shaderFlags.Count; i++) + { + shaderFlags[i].SetUVMode(uvMode, uvModeBitPos, uvModeFlagIndex); + } + _helper.ResetTool.CheckOnValueChange(wrapModeNameTuple); + }; + uvMode = (UVMode) EditorGUI.Popup(popUpRect, (int)uvMode, _uvModeNames); + if (EditorGUI.EndChangeCheck()) + { + drawUVModeEndChangeCheck(); + } + + bool needFoldOut = uvMode != UVMode.DefaultUVChannel && uvMode != UVMode.CommonUV + && uvMode != UVMode.ScreenUV && uvMode != UVMode.MainTex; + bool foldOutState = shaderFlags[0].CheckFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + AnimBool animBool = _helper.GetAnimBool(foldOutFlagBit, foldOutFlagIndex-3, foldOutFlagIndex); + animBool.target = foldOutState; + if (!uvModeHasMixedValue && !needFoldOut) + { + animBool.target = false; + } + else + { + animBool.target = EditorGUI.Foldout(rect, animBool.target, string.Empty, true); + if (isChangeUVMode) + { + animBool.target = true; + } + } + foldOutState = animBool.target; + if (foldOutState) + { + shaderFlags[0].SetFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + } + else + { + shaderFlags[0].ClearFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + } + EditorGUI.LabelField(labelRect,label); + + _helper.ResetTool.DrawResetModifyButton(new Rect(),wrapModeNameTuple, + resetCallBack: () => + { + uvMode = 0; + drawUVModeEndChangeCheck(); + },onValueChangedCallBack: drawUVModeEndChangeCheck,checkHasModifyOnValueChange: () => + { + return shaderFlags[0].GetUVMode(uvModeBitPos, uvModeFlagIndex) != 0; + },checkHasMixedValueOnValueChange:()=>UvModeHasMixedValue(uvModeBitPos, uvModeFlagIndex)); + EditorGUILayout.EndHorizontal(); + _helper.ResetTool.EndResetModifyButtonScope(); + + + + EditorGUI.showMixedValue = false; + + if (needFoldOut||_helper.ResetTool.IsInitResetData) + { + if (!uvModeHasMixedValue) + { + EditorGUI.indentLevel++; + + float faded = animBool.faded; + if (faded == 0) faded = 0.0001f; + EditorGUILayout.BeginFadeGroup(faded); + EditorGUILayout.LabelField("以下设置材质内通用:",EditorStyles.boldLabel); + + + Action drawSpecialUVChannel = () => + { + _helper.DrawPopUp("特殊UV通道选择","_SpecialUVChannelMode", Enum.GetNames(typeof(SpecialUVChannelMode)), + drawOnValueChangedBlock: + specialUVChannelMode => + { + //在OnValueChange的时候。就已经是一起Set了。 + SpecialUVChannelMode spUVMode = (SpecialUVChannelMode)specialUVChannelMode.floatValue; + for (int i = 0; i < shaderFlags.Count; i++) + { + switch (spUVMode) + { + case SpecialUVChannelMode.UV2_Texcoord1: + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1,index:1); + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2,index:1); + break; + case SpecialUVChannelMode.UV3_Texcoord2: + shaderFlags[i].ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1,index:1); + shaderFlags[i].SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2,index:1); + break; + //TODO:如果所有UVMode都没有开启,需要都Clear。 + } + } + },isSharedGlobalParent:true); + }; + + Action drawPolarOrTwirl = () => + { + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitTwril,3,GetAnimBoolIndex(3),"旋转扭曲","_UTwirlEnabled",flagBitsName:W9ParticleShaderFlags.FLAG_BIT_PARTICLE_UTWIRL_ON,isSharedGlobalParent:true,drawBlock:(isToggle) =>{ + _helper.DrawVector4In2Line("_TWParameter","旋转扭曲中心",true); + _helper.DrawFloat("旋转扭曲强度","_TWStrength"); + }); + + _helper.DrawToggleFoldOut(W9ParticleShaderFlags.foldOutBitPolar,3,GetAnimBoolIndex(3),"极坐标", "_PolarCoordinatesEnabled",W9ParticleShaderFlags.FLAG_BIT_PARTICLE_POLARCOORDINATES_ON,isSharedGlobalParent:true,drawBlock:(isToggle) =>{ + // _helper.DrawToggle("极坐标只影响特殊功能","_PolarCordinateOnlySpecialFunciton_Toggle",W9ParticleShaderFlags.FLAG_BIT_PARTICLE_PC_ONLYSPECIALFUNC); + _helper.DrawVector4In2Line("_PCCenter","极坐标中心",true); + _helper.DrawVector4Component("极坐标强度","_PCCenter","z",true,0f,1f); + }); + }; + + Action drawCylinderUV = () => + { + // EditorGUILayout.LabelField("圆柱坐标模式尚未开发完成!"); + EditorGUILayout.LabelField("圆柱模式消耗比较大,慎用"); + _helper.DrawVector4XYZComponet("圆柱坐标旋转","_CylinderUVRotate"); + _helper.DrawVector4XYZComponet("圆柱坐标偏移","_CylinderUVPosOffset"); + Matrix4x4 cylinderMatrix = + Matrix4x4.Translate(_helper.GetProperty("_CylinderUVPosOffset").vectorValue) * + Matrix4x4.Rotate(Quaternion.Euler(_helper.GetProperty("_CylinderUVRotate").vectorValue)); + _helper.GetProperty("_CylinderMatrix0").vectorValue =cylinderMatrix.GetRow(0); + _helper.GetProperty("_CylinderMatrix1").vectorValue =cylinderMatrix.GetRow(1); + _helper.GetProperty("_CylinderMatrix2").vectorValue =cylinderMatrix.GetRow(2); + _helper.GetProperty("_CylinderMatrix3").vectorValue =cylinderMatrix.GetRow(3); + }; + + Action drawWorldPosUV = () => + { + _helper.DrawPopUp("坐标平面", "_WorldSpaceUVModeSelector", _posUVModeNames); + }; + + Action drawObjectPosUV = () => + { + _helper.DrawPopUp("坐标平面", "_ObjectSpaceUVModeSelector", _posUVModeNames); + }; + + if (_helper.ResetTool.IsInitResetData) + { + drawSpecialUVChannel(); + drawPolarOrTwirl(); + drawWorldPosUV(); + drawObjectPosUV(); + } + else + { + switch (uvMode) + { + case UVMode.SpecialUVChannel: + drawSpecialUVChannel(); + break; + case UVMode.PolarOrTwirl: + drawPolarOrTwirl(); + break; + case UVMode.Cylinder: + drawCylinderUV(); + break; + case UVMode.WorldPos: + drawWorldPosUV(); + break; + case UVMode.ObjectPos: + drawObjectPosUV(); + break; + } + } + + EditorGUILayout.EndFadeGroup(); + } + EditorGUI.indentLevel--; + } + EditorGUI.EndDisabledGroup(); + + } + + private string[] _meshSourceModeNames = + { + "粒子系统", + "模型(非粒子发射)", + "2D RawImage", + "2D 精灵", + "2D 材质贴图", + "2D UIParticle" + }; + + internal enum MeshSourceMode + { + Particle, + Mesh, + UIEffectRawImage, + UIEffectSprite, + UIEffectBaseMap, + UIParticle, + UnKnowOrMixed = -1 + } + + bool ColorChannelHasMixedValue(int colorChannelBitPos) + { + W9ParticleShaderFlags.ColorChannel colorChannel = W9ParticleShaderFlags.ColorChannel.UnKnownOrMixedValue; + for (int i = 0; i < shaderFlags.Count; i++) + { + W9ParticleShaderFlags.ColorChannel curChannel = shaderFlags[i].GetColorChanel(colorChannelBitPos); + if (i == 0) + { + colorChannel = curChannel; + } + else + { + if(colorChannel != curChannel) return true; + } + } + + return false; + } + + private string[] _colorChannelNames = { "R", "G", "B", "A" }; + + public void DrawColorChannelSelect(string label, int colorChannelBitPos,int defaultChannel = 0) + { + bool hasMixedValue = ColorChannelHasMixedValue(colorChannelBitPos); + EditorGUI.showMixedValue = hasMixedValue; + (string, string) nameTuple = (label, ""); + + W9ParticleShaderFlags.ColorChannel chanel = shaderFlags[0].GetColorChanel(colorChannelBitPos); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + int index = EditorGUILayout.Popup(label, (int)chanel, + _colorChannelNames); + Action colorChannelOnEndChangeCheck = () => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + shaderFlags[i].SetColorChanel((W9ParticleShaderFlags.ColorChannel)index,colorChannelBitPos); + } + _helper.ResetTool.CheckOnValueChange(nameTuple); + }; + if (EditorGUI.EndChangeCheck()) + { + colorChannelOnEndChangeCheck(); + } + EditorGUI.showMixedValue = false; + _helper.ResetTool.DrawResetModifyButton(new Rect(),nameTuple, + resetCallBack: () => { index = defaultChannel; }, + onValueChangedCallBack: colorChannelOnEndChangeCheck, + checkHasModifyOnValueChange: () => { return shaderFlags[0].GetColorChanel(colorChannelBitPos) != (W9ParticleShaderFlags.ColorChannel)defaultChannel;}, + checkHasMixedValueOnValueChange:()=>ColorChannelHasMixedValue(colorChannelBitPos)); + EditorGUILayout.EndHorizontal(); + _helper.ResetTool.EndResetModifyButtonScope(); + } + + bool PNoiseBlendModeHasMixedValue(int pNoiseBlendModeBitPos) + { + W9ParticleShaderFlags.PNoiseBlendMode pNoiseBlendMode = W9ParticleShaderFlags.PNoiseBlendMode.UnKnownOrMixedValue; + for (int i = 0; i < shaderFlags.Count; i++) + { + W9ParticleShaderFlags.PNoiseBlendMode curMode = shaderFlags[i].GetPNoiseBlendMode(pNoiseBlendModeBitPos); + if (i == 0) + { + pNoiseBlendMode = curMode; + } + else + { + if(pNoiseBlendMode != curMode) return true; + } + } + + return false; + } + + private string[] _pNoiseBlendModeNames = + { + "不使用" , + "Multiply" , + "Min" , + "HardLight" + }; + + void DrawPNoiseBlendModeSelect(string label, int pNoiseBlendModeBitPos,string opacityPropertyName) + { + if(_pNoiseEnabled < 0.5 && !_helper.ResetTool.IsInitResetData) return; + bool hasMixedValue = PNoiseBlendModeHasMixedValue(pNoiseBlendModeBitPos); + EditorGUI.showMixedValue = hasMixedValue; + (string, string) nameTuple = (label, ""); + + W9ParticleShaderFlags.PNoiseBlendMode blendMode = shaderFlags[0].GetPNoiseBlendMode(pNoiseBlendModeBitPos); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + int index = EditorGUILayout.Popup(label+"程序噪波混合", (int)blendMode, _pNoiseBlendModeNames); + Action pNoiseBlendModeOnEndChangeCheck = () => + { + for (int i = 0; i < shaderFlags.Count; i++) + { + shaderFlags[i].SetPNoiseBlendMode((W9ParticleShaderFlags.PNoiseBlendMode)index,pNoiseBlendModeBitPos); + } + _helper.ResetTool.CheckOnValueChange(nameTuple); + }; + if (EditorGUI.EndChangeCheck()) + { + pNoiseBlendModeOnEndChangeCheck(); + } + EditorGUI.showMixedValue = false; + _helper.ResetTool.DrawResetModifyButton(new Rect(),nameTuple, + resetCallBack: () => { index = (int)W9ParticleShaderFlags.PNoiseBlendMode.NotUse; }, + onValueChangedCallBack: pNoiseBlendModeOnEndChangeCheck, + checkHasModifyOnValueChange: () => { return shaderFlags[0].GetPNoiseBlendMode(pNoiseBlendModeBitPos) != W9ParticleShaderFlags.PNoiseBlendMode.NotUse;}, + checkHasMixedValueOnValueChange:()=>PNoiseBlendModeHasMixedValue(pNoiseBlendModeBitPos)); + EditorGUILayout.EndHorizontal(); + _helper.ResetTool.EndResetModifyButtonScope(); + + _helper.DrawSlider("程序噪波混合强度",opacityPropertyName); + + } + + int GetAnimBoolIndex(int foldOutFlagIndex) + { + return foldOutFlagIndex - 3; + } + + // private static readonly FieldInfo _validKeywordsField = typeof(Material) + // .GetField("m_ValidKeywords", BindingFlags.NonPublic | BindingFlags.Instance); + // + // public static string[] GetValidKeywordsDirect(Material material) + // { + // if (_validKeywordsField == null) + // { + // Debug.LogError("m_ValidKeywords field not found!"); + // return null; + // } + // + // var keywords = _validKeywordsField.GetValue(material) as string[]; + // return keywords; + // } + } +} + + diff --git a/Packages/NB_FX/NBShaders/Editor/ParticleBaseGUI.cs.meta b/Packages/NB_FX/NBShaders/Editor/ParticleBaseGUI.cs.meta new file mode 100644 index 00000000..0ef4d295 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Editor/ParticleBaseGUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01d5272ee28d1384d9f555c579592a6b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Editor/ParticleBaseHoudiniVATGUI.cs b/Packages/NB_FX/NBShaders/Editor/ParticleBaseHoudiniVATGUI.cs new file mode 100644 index 00000000..f2e7033e --- /dev/null +++ b/Packages/NB_FX/NBShaders/Editor/ParticleBaseHoudiniVATGUI.cs @@ -0,0 +1,596 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using NBShader; + +namespace NBShaderEditor +{ + internal sealed class ParticleBaseHoudiniVATGUI + { + private readonly ShaderGUIHelper _helper; + + private static readonly string[] SubModeNames = + { + "SoftBody (Deformation)", + "RigidBody (Pieces)", + "Dynamic Remeshing (Lookup)", + "Particle Sprites (Billboard)" + }; + + private static readonly string[] SubModeKeywords = + { + "_HOUDINI_VAT_SOFTBODY", + "_HOUDINI_VAT_RIGIDBODY", + "_HOUDINI_VAT_DYNAMIC_REMESH", + "_HOUDINI_VAT_PARTICLE_SPRITE" + }; + + public ParticleBaseHoudiniVATGUI(ShaderGUIHelper helper) + { + _helper = helper; + } + + public void Draw() + { + DrawSubModeSelector(); + DrawPlaybackSection(); + DrawBoundsSection(); + DrawTextureSection(); + DrawScaleSection(); + DrawParticleSpriteSection(); + DrawFlagsSection(); + SyncKeywords(); + } + + public static void AppendRequiredVertexStreams( + Material material, + List streams, + List streamList) + { + if (material.GetFloat("_VAT_Toggle") <= 0.5f) + { + return; + } + + int subMode = GetMaterialSubMode(material); + bool isParticleMode = IsHoudiniParticleModeEnabled(material); + + AddStream(streams, streamList, ParticleSystemVertexStream.Position, ParticleBaseGUI.streamPositionText); + AddStream(streams, streamList, ParticleSystemVertexStream.Normal, ParticleBaseGUI.streamNormalText); + + switch (subMode) + { + case 0: // SoftBody needs VAT UV1. + AddVatUV1Stream(streams, streamList, isParticleMode); + break; + + case 1: // RigidBody needs VAT UV1, UV2, UV3 (Custom2, vatTexcoord5) + if (isParticleMode) + { + break; + } + + AddVatUV1Stream(streams, streamList, isParticleMode); + AddStream(streams, streamList, ParticleSystemVertexStream.Custom2XYZW, ParticleBaseGUI.streamCustom2Text); + AddStream(streams, streamList, ParticleSystemVertexStream.UV, ParticleBaseGUI.streamUVText); + break; + + case 2: // DynamicRemeshing needs UV0 (texcoords) + AddStream(streams, streamList, ParticleSystemVertexStream.UV, ParticleBaseGUI.streamUVText); + break; + + case 3: // ParticleSprite needs UV0 (corner) + VAT UV1 (particle U/V) + AddStream(streams, streamList, ParticleSystemVertexStream.UV, ParticleBaseGUI.streamUVText); + AddVatUV1Stream(streams, streamList, isParticleMode); + break; + } + } + + private List mats => _helper.mats; + + private bool IsResetToolInitializing() + { + return _helper.ResetTool != null && _helper.ResetTool.IsInitResetData; + } + + private bool TryGetCurrentSubMode(out int subMode) + { + MaterialProperty property = _helper.GetProperty("_HoudiniVATSubMode"); + if (property == null || property.hasMixedValue) + { + subMode = -1; + return false; + } + + subMode = Mathf.Clamp(Mathf.RoundToInt(property.floatValue), 0, SubModeNames.Length - 1); + return true; + } + + private bool IsSubMode(params int[] subModes) + { + if (IsResetToolInitializing()) + { + return true; + } + + if (!TryGetCurrentSubMode(out int currentSubMode)) + { + return false; + } + + for (int i = 0; i < subModes.Length; i++) + { + if (currentSubMode == subModes[i]) + { + return true; + } + } + + return false; + } + + private bool TryGetFloatProperty(string propertyName, out MaterialProperty property) + { + property = _helper.GetProperty(propertyName); + return property != null && !property.hasMixedValue; + } + + private bool IsFloatPropertyOn(string propertyName) + { + return TryGetFloatProperty(propertyName, out MaterialProperty property) && property.floatValue > 0.5f; + } + + private bool IsFloatPropertyOff(string propertyName) + { + return TryGetFloatProperty(propertyName, out MaterialProperty property) && property.floatValue <= 0.5f; + } + + private bool IsFloatPropertyMixed(string propertyName) + { + MaterialProperty property = _helper.GetProperty(propertyName); + return property != null && property.hasMixedValue; + } + + private bool ShouldDrawWhenFloatOn(string propertyName) + { + return IsResetToolInitializing() || IsFloatPropertyMixed(propertyName) || IsFloatPropertyOn(propertyName); + } + + private bool ShouldDrawWhenFloatOff(string propertyName) + { + return IsResetToolInitializing() || IsFloatPropertyMixed(propertyName) || IsFloatPropertyOff(propertyName); + } + + private static int GetMaterialSubMode(Material material) + { + if (!material.HasProperty("_HoudiniVATSubMode")) + { + return 0; + } + + return Mathf.Clamp(Mathf.RoundToInt(material.GetFloat("_HoudiniVATSubMode")), 0, SubModeNames.Length - 1); + } + + private static bool IsHoudiniParticleModeEnabled(Material material) + { + if (material == null || + !material.HasProperty("_VAT_Toggle") || + !material.HasProperty("_VATMode") || + !material.HasProperty("_MeshSourceMode") || + material.GetFloat("_VAT_Toggle") <= 0.5f || + Mathf.RoundToInt(material.GetFloat("_VATMode")) != (int)ParticleBaseGUI.VATMode.Houdini) + { + return false; + } + + ParticleBaseGUI.MeshSourceMode meshSourceMode = (ParticleBaseGUI.MeshSourceMode)Mathf.RoundToInt(material.GetFloat("_MeshSourceMode")); + return meshSourceMode == ParticleBaseGUI.MeshSourceMode.Particle || + meshSourceMode == ParticleBaseGUI.MeshSourceMode.UIParticle; + } + + private void DrawSubModeSelector() + { + _helper.DrawPopUp("Houdini VAT Sub Mode", "_HoudiniVATSubMode", SubModeNames); + if (HasUnsupportedParticleMode()) + { + EditorGUILayout.HelpBox("该 Houdini VAT 类型需要 Mesh 多 UV 数据,不支持 ParticleSystem VertexStream 模式。", MessageType.Warning); + } + } + + private void DrawPlaybackSection() + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Playback", EditorStyles.boldLabel); + + _helper.DrawToggle("Auto Playback", "_B_autoPlayback"); + + if (ShouldDrawWhenFloatOff("_B_autoPlayback")) + { + _helper.DrawFloat("Display Frame", "_displayFrame"); + } + + DrawFrameCustomDataSelect(); + + _helper.DrawFloat("Game Time at First Frame", "_gameTimeAtFirstFrame"); + _helper.DrawFloat("Playback Speed", "_playbackSpeed"); + _helper.DrawFloat("Houdini FPS", "_houdiniFPS"); + _helper.DrawToggle("Interframe Interpolation", "_B_interpolate"); + + if (IsSubMode(1)) // RigidBody + { + _helper.DrawToggle("Animate First Frame", "_animateFirstFrame"); + } + } + + private void DrawBoundsSection() + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Bounds Metadata", EditorStyles.boldLabel); + + _helper.DrawFloat("Bound Min X", "_boundMinX"); + _helper.DrawFloat("Bound Min Y", "_boundMinY"); + _helper.DrawFloat("Bound Min Z", "_boundMinZ"); + _helper.DrawFloat("Bound Max X", "_boundMaxX"); + _helper.DrawFloat("Bound Max Y", "_boundMaxY"); + _helper.DrawFloat("Bound Max Z", "_boundMaxZ"); + } + + private void DrawFrameCustomDataSelect() + { + const int dataBitPos = W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME; + const int dataIndex = 2; + W9ParticleShaderFlags.CutomDataComponent component = GetCurrentCustomDataComponent(dataBitPos, dataIndex); + if (!IsAnyHoudiniParticleModeEnabled() || _helper.shaderFlags == null || _helper.shaderFlags.Length == 0) + { + ClearFrameCustomData(dataBitPos, dataIndex); + return; + } + + (string, string) nameTuple = ("VATFrameCustomData", ""); + + EditorGUI.showMixedValue = CustomDataHasMixedValue(dataBitPos, dataIndex); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + component = (W9ParticleShaderFlags.CutomDataComponent)EditorGUILayout.Popup(new GUIContent("VAT Frame CustomData"), (int)component, ParticleBaseGUI.CustomDataOptions); + EditorGUI.showMixedValue = false; + + Action applySelection = () => + { + for (int i = 0; i < _helper.shaderFlags.Length; i++) + { + if (_helper.shaderFlags[i] is W9ParticleShaderFlags flags) + { + flags.SetCustomDataFlag(component, dataBitPos, dataIndex); + } + } + + _helper.ResetTool.CheckOnValueChange(nameTuple); + }; + + if (EditorGUI.EndChangeCheck()) + { + applySelection(); + } + + _helper.ResetTool.DrawResetModifyButton( + new Rect(), + nameTuple, + resetCallBack: () => + { + component = W9ParticleShaderFlags.CutomDataComponent.Off; + applySelection(); + }, + onValueChangedCallBack: applySelection, + checkHasModifyOnValueChange: () => GetCurrentCustomDataComponent(dataBitPos, dataIndex) != W9ParticleShaderFlags.CutomDataComponent.Off, + checkHasMixedValueOnValueChange: () => CustomDataHasMixedValue(dataBitPos, dataIndex)); + EditorGUILayout.EndHorizontal(); + _helper.ResetTool.EndResetModifyButtonScope(); + } + + private void ClearFrameCustomData(int dataBitPos, int dataIndex) + { + if (_helper.shaderFlags == null) + { + return; + } + + for (int i = 0; i < _helper.shaderFlags.Length; i++) + { + if (_helper.shaderFlags[i] is W9ParticleShaderFlags flags) + { + flags.SetCustomDataFlag(W9ParticleShaderFlags.CutomDataComponent.Off, dataBitPos, dataIndex); + } + } + } + + private W9ParticleShaderFlags.CutomDataComponent GetCurrentCustomDataComponent(int dataBitPos, int dataIndex) + { + if (_helper.shaderFlags == null || _helper.shaderFlags.Length == 0) + { + return W9ParticleShaderFlags.CutomDataComponent.Off; + } + + if (_helper.shaderFlags[0] is W9ParticleShaderFlags flags) + { + return flags.GetCustomDataFlag(dataBitPos, dataIndex); + } + + return W9ParticleShaderFlags.CutomDataComponent.Off; + } + + private bool CustomDataHasMixedValue(int dataBitPos, int dataIndex) + { + if (_helper.shaderFlags == null || _helper.shaderFlags.Length == 0) + { + return false; + } + + W9ParticleShaderFlags.CutomDataComponent component = W9ParticleShaderFlags.CutomDataComponent.UnKnownOrMixed; + for (int i = 0; i < _helper.shaderFlags.Length; i++) + { + if (!(_helper.shaderFlags[i] is W9ParticleShaderFlags flags)) + { + continue; + } + + W9ParticleShaderFlags.CutomDataComponent current = flags.GetCustomDataFlag(dataBitPos, dataIndex); + if (component == W9ParticleShaderFlags.CutomDataComponent.UnKnownOrMixed) + { + component = current; + continue; + } + + if (component != current) + { + return true; + } + } + + return false; + } + + private bool IsAnyHoudiniParticleModeEnabled() + { + if (_helper.mats == null) + { + return false; + } + + for (int i = 0; i < _helper.mats.Count; i++) + { + if (IsHoudiniParticleModeEnabled(_helper.mats[i])) + { + return true; + } + } + + return false; + } + + private bool HasUnsupportedParticleMode() + { + if (_helper.mats == null) + { + return false; + } + + for (int i = 0; i < _helper.mats.Count; i++) + { + if (IsUnsupportedParticleMode(_helper.mats[i])) + { + return true; + } + } + + return false; + } + + private static bool IsUnsupportedParticleMode(Material material) + { + return IsHoudiniParticleModeEnabled(material) && GetMaterialSubMode(material) == 1; + } + + private void DrawTextureSection() + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Textures", EditorStyles.boldLabel); + + _helper.DrawTexture("Position Texture", "_posTexture", drawScaleOffset: false, drawWrapMode: false); + + if (ShouldDrawWhenFloatOn("_B_LOAD_POS_TWO_TEX")) + { + _helper.DrawTexture("Position Texture 2", "_posTexture2", drawScaleOffset: false, drawWrapMode: false); + } + + if (ShouldDrawRotationTexture()) + { + _helper.DrawTexture("Rotation Texture", "_rotTexture", drawScaleOffset: false, drawWrapMode: false); + } + + if (ShouldDrawWhenFloatOn("_B_LOAD_COL_TEX")) + { + _helper.DrawTexture("Color Texture", "_colTexture", drawScaleOffset: false, drawWrapMode: false); + } + + if (IsSubMode(2) || ShouldDrawWhenFloatOn("_B_LOAD_LOOKUP_TABLE")) + { + _helper.DrawTexture("Lookup Table", "_lookupTable", drawScaleOffset: false, drawWrapMode: false); + } + } + + private void DrawScaleSection() + { + if (IsSubMode(1, 3)) + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Scale", EditorStyles.boldLabel); + + _helper.DrawFloat("Global Piece Scale Multiplier", "_globalPscaleMul"); + _helper.DrawToggle("Piece Scales in Position Alpha", "_B_pscaleAreInPosA"); + } + } + + private void DrawParticleSpriteSection() + { + if (!IsSubMode(3)) + { + return; + } + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Particle Sprite", EditorStyles.boldLabel); + + _helper.DrawFloat("Width Base Scale", "_widthBaseScale"); + _helper.DrawFloat("Height Base Scale", "_heightBaseScale"); + + _helper.DrawToggle("Hide Overlapping Origin", "_B_hideOverlappingOrigin"); + if (ShouldDrawWhenFloatOn("_B_hideOverlappingOrigin")) + { + _helper.DrawFloat("Origin Effective Radius", "_originRadius"); + } + + _helper.DrawToggle("Particles Can Spin", "_B_CAN_SPIN"); + + if (ShouldDrawWhenFloatOn("_B_CAN_SPIN")) + { + _helper.DrawToggle("Compute Spin from Heading", "_B_spinFromHeading"); + + if (ShouldDrawWhenFloatOff("_B_spinFromHeading")) + { + _helper.DrawFloat("Particle Spin Phase", "_spinPhase"); + } + + _helper.DrawFloat("Scale by Velocity Amount", "_scaleByVelAmount"); + } + + _helper.DrawFloat("Particle Texture U Scale", "_particleTexUScale"); + _helper.DrawFloat("Particle Texture V Scale", "_particleTexVScale"); + } + + private void DrawFlagsSection() + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Flags", EditorStyles.boldLabel); + + _helper.DrawToggle("Positions Require Two Textures", "_B_LOAD_POS_TWO_TEX"); + + if (ShouldDrawCompressedNormalsToggle()) + { + _helper.DrawToggle("Use Compressed Normals (no rotTex)", "_B_UNLOAD_ROT_TEX"); + } + + _helper.DrawToggle("Load Color Texture", "_B_LOAD_COL_TEX"); + + if (IsSubMode(2)) + { + _helper.DrawToggle("Load Lookup Table", "_B_LOAD_LOOKUP_TABLE"); + } + } + + private bool ShouldDrawRotationTexture() + { + if (IsResetToolInitializing()) + { + return true; + } + + if (!TryGetCurrentSubMode(out int subMode) || subMode == 3) + { + return false; + } + + return IsFloatPropertyMixed("_B_UNLOAD_ROT_TEX") || IsFloatPropertyOff("_B_UNLOAD_ROT_TEX"); + } + + private bool ShouldDrawCompressedNormalsToggle() + { + if (IsResetToolInitializing()) + { + return true; + } + + return TryGetCurrentSubMode(out int subMode) && subMode != 3; + } + + private void SyncKeywords() + { + if (mats == null) + { + return; + } + + foreach (Material mat in mats) + { + if (mat == null) + { + continue; + } + + SyncKeywords(mat); + } + } + + internal static void SyncKeywords(Material mat) + { + if (mat == null) + { + return; + } + + SetSubModeKeyword(mat, GetMaterialSubMode(mat)); + } + + internal static void ClearKeywords(Material mat) + { + if (mat == null) + { + return; + } + + SetSubModeKeyword(mat, -1); + } + + private static void SetSubModeKeyword(Material mat, int enabledIndex) + { + for (int i = 0; i < SubModeKeywords.Length; i++) + { + mat.DisableKeyword(SubModeKeywords[i]); + } + + if (enabledIndex >= 0 && enabledIndex < SubModeKeywords.Length) + { + mat.EnableKeyword(SubModeKeywords[enabledIndex]); + } + } + + private static void AddStream( + List streams, + List streamList, + ParticleSystemVertexStream stream, + string streamLabel) + { + if (streams.Contains(stream)) + { + return; + } + + streams.Add(stream); + streamList.Add(streamLabel); + } + + private static void AddVatUV1Stream( + List streams, + List streamList, + bool isParticleMode) + { + if (isParticleMode) + { + AddStream(streams, streamList, ParticleSystemVertexStream.UV2, ParticleBaseGUI.streamUV2Text); + return; + } + + AddStream(streams, streamList, ParticleSystemVertexStream.Custom1XYZW, ParticleBaseGUI.streamCustom1Text); + } + } +} diff --git a/Packages/NB_FX/NBShaders/Editor/ParticleBaseHoudiniVATGUI.cs.meta b/Packages/NB_FX/NBShaders/Editor/ParticleBaseHoudiniVATGUI.cs.meta new file mode 100644 index 00000000..d282579f --- /dev/null +++ b/Packages/NB_FX/NBShaders/Editor/ParticleBaseHoudiniVATGUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1fb3d41607849d44486fbc2549077b59 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Editor/ParticleBaseTyflowVATGUI.cs b/Packages/NB_FX/NBShaders/Editor/ParticleBaseTyflowVATGUI.cs new file mode 100644 index 00000000..c01fbbf6 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Editor/ParticleBaseTyflowVATGUI.cs @@ -0,0 +1,386 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using NBShader; + +namespace NBShaderEditor +{ + internal sealed class ParticleBaseTyflowVATGUI + { + private const string TyflowSubModeProperty = "_TyFlowVATSubMode"; + private const int TyflowSkinModeStart = 2; + private const float TyflowParticleHighestNonSkinMode = 1.5f; + + private readonly ShaderGUIHelper _helper; + + private static readonly string[] TyflowAnimationModeNames = + { + "Absolute positions", + "Relative offsets", + "Skin (R)", + "Skin (PR)", + "Skin (PRSAVE)", + "Skin (PRSXYZ)" + }; + + private static readonly string[] TyflowModeKeywords = + { + "_TYFLOW_VAT_ABSOLUTE", + "_TYFLOW_VAT_RELATIVE", + "_TYFLOW_VAT_SKIN_R", + "_TYFLOW_VAT_SKIN_PR", + "_TYFLOW_VAT_SKIN_PRSAVE", + "_TYFLOW_VAT_SKIN_PRSXYZ" + }; + + public ParticleBaseTyflowVATGUI(ShaderGUIHelper helper) + { + _helper = helper; + } + + public void Draw() + { + DrawTyflowSettings(); + SyncKeywords(); + } + + public static void AppendRequiredVertexStreams( + Material material, + List streams, + List streamList) + { + if (!IsTyflowParticleModeEnabled(material)) + { + return; + } + + AddStream(streams, streamList, ParticleSystemVertexStream.UV2, ParticleBaseGUI.streamUV2Text); + } + + private void DrawTyflowSettings() + { + _helper.DrawTexture("VAT texture", "_VATTex", drawScaleOffset: false, drawWrapMode: false); + _helper.DrawFloat("ImportScale", "_ImportScale"); + _helper.DrawPopUp("TyFlow VAT Sub Mode", TyflowSubModeProperty, TyflowAnimationModeNames); + + if (HasUnsupportedParticleMode()) + { + EditorGUILayout.HelpBox("该 TyFlow VAT 类型需要 Mesh 多 UV 数据,不支持 ParticleSystem VertexStream 模式。", MessageType.Warning); + } + else if (HasParticleUV2Conflict()) + { + EditorGUILayout.HelpBox("TyFlow VAT uses UV2 (TEXCOORD0.zw) as vertexIndex / vertexCount in ParticleSystem mode. Flipbook blending or Special UV (UV2) conflicts with it; VAT takes priority.", MessageType.Warning); + } + + _helper.DrawToggle("Deforming skin", "_DeformingSkin"); + _helper.DrawFloat("Skin bone count", "_SkinBoneCount"); + _helper.DrawToggle("RGBA encoded", "_RGBAEncoded"); + _helper.DrawToggle("RGBA half", "_RGBAHalf"); + _helper.DrawToggle("Gamma correction", "_LinearToGamma"); + _helper.DrawToggle("VAT includes normals", "_VATIncludesNormals"); + _helper.DrawToggle("Affects shadows", "_AffectsShadows"); + _helper.DrawFloat("Frame", "_Frame"); + DrawFrameCustomDataSelect(); + _helper.DrawFloat("Frames", "_Frames"); + _helper.DrawToggle("Frame interpolation", "_FrameInterpolation"); + _helper.DrawToggle("Loop", "_Loop"); + _helper.DrawToggle("Interpolate loop", "_InterpolateLoop"); + _helper.DrawToggle("Autoplay", "_Autoplay"); + _helper.DrawFloat("AutoplaySpeed", "_AutoplaySpeed"); + } + + private void DrawFrameCustomDataSelect() + { + const int dataBitPos = W9ParticleShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME; + const int dataIndex = 2; + W9ParticleShaderFlags.CutomDataComponent component = GetCurrentCustomDataComponent(dataBitPos, dataIndex); + if (!IsAnyTyflowParticleModeEnabled() || _helper.shaderFlags == null || _helper.shaderFlags.Length == 0) + { + if (component != W9ParticleShaderFlags.CutomDataComponent.Off) + { + component = W9ParticleShaderFlags.CutomDataComponent.Off; + for (int i = 0; i < _helper.shaderFlags.Length; i++) + { + if (_helper.shaderFlags[i] is W9ParticleShaderFlags flags) + { + flags.SetCustomDataFlag(component, dataBitPos, dataIndex); + } + } + } + + return; + } + + (string, string) nameTuple = ("VATFrameCustomData", ""); + + EditorGUI.showMixedValue = CustomDataHasMixedValue(dataBitPos, dataIndex); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + component = (W9ParticleShaderFlags.CutomDataComponent)EditorGUILayout.Popup(new GUIContent("VAT Frame CustomData"), (int)component, ParticleBaseGUI.CustomDataOptions); + EditorGUI.showMixedValue = false; + + Action applySelection = () => + { + for (int i = 0; i < _helper.shaderFlags.Length; i++) + { + if (_helper.shaderFlags[i] is W9ParticleShaderFlags flags) + { + flags.SetCustomDataFlag(component, dataBitPos, dataIndex); + } + } + + _helper.ResetTool.CheckOnValueChange(nameTuple); + }; + + if (EditorGUI.EndChangeCheck()) + { + applySelection(); + } + + _helper.ResetTool.DrawResetModifyButton( + new Rect(), + nameTuple, + resetCallBack: () => + { + component = W9ParticleShaderFlags.CutomDataComponent.Off; + applySelection(); + }, + onValueChangedCallBack: applySelection, + checkHasModifyOnValueChange: () => GetCurrentCustomDataComponent(dataBitPos, dataIndex) != W9ParticleShaderFlags.CutomDataComponent.Off, + checkHasMixedValueOnValueChange: () => CustomDataHasMixedValue(dataBitPos, dataIndex)); + EditorGUILayout.EndHorizontal(); + _helper.ResetTool.EndResetModifyButtonScope(); + } + + private W9ParticleShaderFlags.CutomDataComponent GetCurrentCustomDataComponent(int dataBitPos, int dataIndex) + { + if (_helper.shaderFlags == null || _helper.shaderFlags.Length == 0) + { + return W9ParticleShaderFlags.CutomDataComponent.Off; + } + + if (_helper.shaderFlags[0] is W9ParticleShaderFlags flags) + { + return flags.GetCustomDataFlag(dataBitPos, dataIndex); + } + + return W9ParticleShaderFlags.CutomDataComponent.Off; + } + + private bool CustomDataHasMixedValue(int dataBitPos, int dataIndex) + { + if (_helper.shaderFlags == null || _helper.shaderFlags.Length == 0) + { + return false; + } + + W9ParticleShaderFlags.CutomDataComponent component = W9ParticleShaderFlags.CutomDataComponent.UnKnownOrMixed; + for (int i = 0; i < _helper.shaderFlags.Length; i++) + { + if (!(_helper.shaderFlags[i] is W9ParticleShaderFlags flags)) + { + continue; + } + + W9ParticleShaderFlags.CutomDataComponent current = flags.GetCustomDataFlag(dataBitPos, dataIndex); + if (component == W9ParticleShaderFlags.CutomDataComponent.UnKnownOrMixed) + { + component = current; + continue; + } + + if (component != current) + { + return true; + } + } + + return false; + } + + private bool HasUnsupportedParticleMode() + { + if (_helper.mats == null) + { + return false; + } + + for (int i = 0; i < _helper.mats.Count; i++) + { + if (IsUnsupportedParticleMode(_helper.mats[i])) + { + return true; + } + } + + return false; + } + + private bool IsAnyTyflowParticleModeEnabled() + { + if (_helper.mats == null) + { + return false; + } + + for (int i = 0; i < _helper.mats.Count; i++) + { + if (IsTyflowParticleModeEnabled(_helper.mats[i])) + { + return true; + } + } + + return false; + } + + private bool HasParticleUV2Conflict() + { + if (_helper.mats == null || _helper.mats.Count == 0 || _helper.shaderFlags == null || _helper.shaderFlags.Length == 0) + { + return false; + } + + for (int i = 0; i < _helper.mats.Count; i++) + { + Material mat = _helper.mats[i]; + if (!IsTyflowParticleModeEnabled(mat)) + { + continue; + } + + W9ParticleShaderFlags flags = _helper.shaderFlags[i] as W9ParticleShaderFlags; + if (flags == null) + { + continue; + } + + bool usesFlipbookBlending = mat.IsKeywordEnabled("_FLIPBOOKBLENDING_ON"); + bool usesSpecialUVOnUV2 = flags.CheckIsUVModeOn(W9ParticleShaderFlags.UVMode.SpecialUVChannel) && + !flags.CheckFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1); + if (usesFlipbookBlending || usesSpecialUVOnUV2) + { + return true; + } + } + + return false; + } + + private static bool IsTyflowParticleModeEnabled(Material material) + { + if (material == null || + !material.HasProperty("_VAT_Toggle") || + !material.HasProperty("_VATMode") || + !material.HasProperty("_MeshSourceMode") || + material.GetFloat("_VAT_Toggle") <= 0.5f || + Mathf.RoundToInt(material.GetFloat("_VATMode")) != (int)ParticleBaseGUI.VATMode.Tyflow) + { + return false; + } + + ParticleBaseGUI.MeshSourceMode meshSourceMode = (ParticleBaseGUI.MeshSourceMode)Mathf.RoundToInt(material.GetFloat("_MeshSourceMode")); + if (meshSourceMode != ParticleBaseGUI.MeshSourceMode.Particle && + meshSourceMode != ParticleBaseGUI.MeshSourceMode.UIParticle) + { + return false; + } + + return GetMaterialSubMode(material) <= TyflowParticleHighestNonSkinMode; + } + + private static bool IsUnsupportedParticleMode(Material material) + { + if (material == null || + !material.HasProperty("_VAT_Toggle") || + !material.HasProperty("_VATMode") || + !material.HasProperty("_MeshSourceMode") || + material.GetFloat("_VAT_Toggle") <= 0.5f || + Mathf.RoundToInt(material.GetFloat("_VATMode")) != (int)ParticleBaseGUI.VATMode.Tyflow) + { + return false; + } + + ParticleBaseGUI.MeshSourceMode meshSourceMode = (ParticleBaseGUI.MeshSourceMode)Mathf.RoundToInt(material.GetFloat("_MeshSourceMode")); + if (meshSourceMode != ParticleBaseGUI.MeshSourceMode.Particle && + meshSourceMode != ParticleBaseGUI.MeshSourceMode.UIParticle) + { + return false; + } + + return GetMaterialSubMode(material) >= TyflowSkinModeStart; + } + + private static int GetMaterialSubMode(Material material) + { + if (!material.HasProperty(TyflowSubModeProperty)) + { + return 0; + } + + return Mathf.Clamp(Mathf.RoundToInt(material.GetFloat(TyflowSubModeProperty)), 0, TyflowModeKeywords.Length - 1); + } + + private void SyncKeywords() + { + if (_helper.mats == null) + { + return; + } + + for (int i = 0; i < _helper.mats.Count; i++) + { + SyncKeywords(_helper.mats[i]); + } + } + + internal static void SyncKeywords(Material mat) + { + if (mat == null) + { + return; + } + + SetSubModeKeyword(mat, GetMaterialSubMode(mat)); + } + + internal static void ClearKeywords(Material mat) + { + if (mat == null) + { + return; + } + + SetSubModeKeyword(mat, -1); + } + + private static void SetSubModeKeyword(Material mat, int enabledIndex) + { + for (int i = 0; i < TyflowModeKeywords.Length; i++) + { + mat.DisableKeyword(TyflowModeKeywords[i]); + } + + if (enabledIndex >= 0 && enabledIndex < TyflowModeKeywords.Length) + { + mat.EnableKeyword(TyflowModeKeywords[enabledIndex]); + } + } + + private static void AddStream( + List streams, + List streamList, + ParticleSystemVertexStream stream, + string streamLabel) + { + if (streams.Contains(stream)) + { + return; + } + + streams.Add(stream); + streamList.Add(streamLabel); + } + } +} diff --git a/Packages/NB_FX/NBShaders/Editor/ParticleBaseTyflowVATGUI.cs.meta b/Packages/NB_FX/NBShaders/Editor/ParticleBaseTyflowVATGUI.cs.meta new file mode 100644 index 00000000..986185ff --- /dev/null +++ b/Packages/NB_FX/NBShaders/Editor/ParticleBaseTyflowVATGUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f8ef4dd3fb2478e9fd8071745d57eca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Editor/com.xuanxuan.nb.shaders.Editor.asmdef b/Packages/NB_FX/NBShaders/Editor/com.xuanxuan.nb.shaders.Editor.asmdef new file mode 100644 index 00000000..d6a97061 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Editor/com.xuanxuan.nb.shaders.Editor.asmdef @@ -0,0 +1,20 @@ +{ + "name": "com.xuanxuan.nb.shaders.Editor", + "rootNamespace": "", + "references": [ + "GUID:0e3b0e6ce60c7a34094f8f9822c0b7f2", + "GUID:8495541fcd41b0c40b5b6e6e7a7639d1", + "GUID:8f9e4d586616f13449cfeb86c5f704c2" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/NB_FX/NBShaders/Editor/com.xuanxuan.nb.shaders.Editor.asmdef.meta b/Packages/NB_FX/NBShaders/Editor/com.xuanxuan.nb.shaders.Editor.asmdef.meta new file mode 100644 index 00000000..a60870d2 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Editor/com.xuanxuan.nb.shaders.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5e03fab8dc9c256468083d9bc82a73c3 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Runtime.meta b/Packages/NB_FX/NBShaders/Runtime.meta new file mode 100644 index 00000000..ce5efe5a --- /dev/null +++ b/Packages/NB_FX/NBShaders/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4684518ac782305428f8c0434c85d1c0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Runtime/W9ParticleShaderFlags.cs b/Packages/NB_FX/NBShaders/Runtime/W9ParticleShaderFlags.cs new file mode 100644 index 00000000..10c1896b --- /dev/null +++ b/Packages/NB_FX/NBShaders/Runtime/W9ParticleShaderFlags.cs @@ -0,0 +1,773 @@ +using UnityEngine; + +namespace NBShader +{ + public class W9ParticleShaderFlags : ShaderFlagsBase + { + public const string FlagsName = "_W9ParticleShaderFlags"; + public static int FlagsId = Shader.PropertyToID(FlagsName); + + + public const string Flags1Name = "_W9ParticleShaderFlags1"; + public static int Flags1Id = Shader.PropertyToID(Flags1Name); + + public const string WrapFlagsName = "_W9ParticleShaderWrapFlags"; + public static int WrapFlagsId = Shader.PropertyToID(WrapFlagsName); + + public const string foldOutFlagName = "_W9ParticleShaderGUIFoldToggle"; + public static int foldOutFlagId = Shader.PropertyToID(foldOutFlagName); + + public const string foldOutFlagName1 = "_W9ParticleShaderGUIFoldToggle1"; + public static int foldOutFlagId1 = Shader.PropertyToID(foldOutFlagName1); + + public const string foldOutFlagName2 = "_W9ParticleShaderGUIFoldToggle2"; + public static int foldOutFlagId2 = Shader.PropertyToID(foldOutFlagName2); + + public const string colorChannelFlagName = "_W9ParticleShaderColorChannelFlag"; + public static int colorChannelFlagId = Shader.PropertyToID(colorChannelFlagName); + + public const string pNoiseBlendFlagName = "_W9ParticleShaderPNoiseBlendFlag"; + public static int pNoiseBlendFlagId = Shader.PropertyToID(pNoiseBlendFlagName); + + // public const string WrapFlags2Name = "_W9ParticleShaderWrapFlags2"; + // public static int WrapFlags2Id = Shader.PropertyToID(WrapFlags2Name); + + public override int GetShaderFlagsId(int index = 0) + { + switch (index) + { + case 0: + return FlagsId; + + case 1: + return Flags1Id; + + case 2: + return WrapFlagsId; + + //FoldOut必须要紧挨着,因为按照Index去拿AnimBool + case 3: + return foldOutFlagId; + + case 4: + return foldOutFlagId1; + + case 5: + return foldOutFlagId2; + + case 6: + return colorChannelFlagId; + + case 7: + return pNoiseBlendFlagId; + // case 8: + // return WrapFlags2Id; + + default: + return FlagsId; + } + } + + protected override string GetShaderFlagsName(int index = 0) + { + switch (index) + { + case 0: + return FlagsName; + + case 1: + return Flags1Name; + + case 2: + return WrapFlagsName; + + case 3: + return foldOutFlagName; + + case 4: + return foldOutFlagName1; + + case 5: + return colorChannelFlagName; + + default: + return FlagsName; + } + } + + + + + + public W9ParticleShaderFlags(Material material = null) : base(material) + { + } + + public const int FLAG_BIT_SATURABILITY_ON = 1 << 0; + public const int FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE = 1 << 1; + public const int FLAG_BIT_PARTICLE_FRESNEL_FADE_ON = 1 << 2; + public const int FLAG_BIT_PARTICLE_FRESNEL_COLOR_ON = 1 << 3; + public const int FLAG_BIT_PARTICLE_USETEXCOORD2 = 1 << 4; + public const int FLAG_BIT_PARTICLE_DISTANCEFADE_ON = 1 << 5; + public const int FLAG_BIT_PARTICLE_CHORATICABERRAT = 1 << 6; + public const int FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON = 1 << 7; + public const int FLAG_BIT_PARTICLE_POLARCOORDINATES_ON = 1 << 8; + public const int FLAG_BIT_PARTICLE_UTWIRL_ON = 1 << 9; + public const int FLAG_BIT_PARTICLE_LINEARTOGAMMA_ON = 1 << 10; + public const int FLAG_BIT_PARTICLE_FRESNEL_ON = 1 << 11; + public const int FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON = 1 << 12; + public const int FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA = 1 << 13; + public const int FLAG_BIT_PARTICLE_UIEFFECT_ON = 1 << 14; + public const int FLAG_BIT_PARTICLE_UNSCALETIME_ON = 1 << 15; + public const int FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON = 1 << 16; + public const int FLAG_BIT_PARTICLE_CUSTOMDATA1_ON = 1 << 17; + public const int FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON = 1 << 18; + public const int FLAG_BIT_HUESHIFT_ON = 1 << 19; + public const int FLAG_BIT_PARTICLE_CUSTOMDATA2_ON = 1 << 20; + public const int FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE = 1 << 21; + public const int FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX = 1 << 22; + public const int FLAG_BIT_PARTICLE_RAMP_COLOR_MAP_MODE_ON = 1 << 23; + public const int FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD = 1 << 24; + public const int FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE = 1 << 25; + public const int FLAG_BIT_PARTICLE_DISSOLVE_RAMP_MAP = 1 << 26; + public const int FLAG_BIT_PARTICLE_DISSOLVE_MASK = 1 << 27; + public const int FLAG_BIT_PARTICLE_BACKCOLOR = 1 << 28; + public const int FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA = 1 << 29; + public const int FLAG_BIT_PARTICLE_VERTEX_OFFSET_ON = 1 << 30; + public const int FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR = 1 << 31; + + public const int FLAG_BIT_PARTICLE_1_DEPTH_OUTLINE = 1 << 0; + public const int FLAG_BIT_PARTICLE_1_PARALLAX_MAPPING = 1 << 1; + public const int FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT = 1 << 2; + public const int FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT = 1 << 3; + public const int FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT = 1 << 4; + public const int FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK = 1 << 5; + public const int FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY = 1 << 6; + public const int FLAG_BIT_PARTICLE_1_MASK_REFINE = 1 << 7; + public const int FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE = 1 << 8; + public const int FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR = 1 << 9; + public const int FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE = 1 << 10; + public const int FLAG_BIT_PARTICLE_1_DISSOVLE_USE_RAMP = 1 << 11; + public const int FLAG_BIT_PARTICLE_1_MASK_MAP2 = 1 << 12; + public const int FLAG_BIT_PARTICLE_1_MASK_MAP3 = 1 << 13; + public const int FLAG_BIT_PARTICLE_1_NOISE_MASKMAP = 1 << 14; + public const int FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER = 1 << 15; + public const int FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI = 1 << 16; + public const int FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE = 1 << 17; + public const int FLAG_BIT_PARTICLE_1_USE_TEXCOORD1 = 1 << 18; + public const int FLAG_BIT_PARTICLE_1_USE_TEXCOORD2 = 1 << 19; + public const int FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE = 1 << 20; + public const int FLAG_BIT_PARTICLE_1_UV_FROM_MESH = 1 << 21; //3D条件下,如果不是来源于Mesh,就默认来源于粒子。 + public const int FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE = 1 << 22; //3D条件下,如果不是来源于Mesh,就默认来源于粒子。 + public const int FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM = 1 << 23; //3D条件下,如果不是来源于Mesh,就默认来源于粒子。 + public const int FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST = 1 << 24; + public const int FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO = 1 << 25; + public const int FLAG_BIT_PARTICLE_1_VERTEXOFFSET_MASKMAP = 1 << 26; + public const int FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE = 1 << 27; + public const int FLAG_BIT_PARTICLE_1_BUMP_TEX_UV_FOLLOW_MAINTEX = 1 << 28; + public const int FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP = 1 << 29; + public const int FLAG_BIT_PARTICLE_1_MATCAP_MULTY_MODE = 1 << 30; + + + public const int FLAG_BIT_WRAPMODE_BASEMAP = 1 << 0; + public const int FLAG_BIT_WRAPMODE_MASKMAP = 1 << 1; + public const int FLAG_BIT_WRAPMODE_MASKMAP2 = 1 << 2; + public const int FLAG_BIT_WRAPMODE_NOISEMAP = 1 << 3; + public const int FLAG_BIT_WRAPMODE_EMISSIONMAP = 1 << 4; + public const int FLAG_BIT_WRAPMODE_DISSOLVE_MAP = 1 << 5; + public const int FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP = 1 << 6; + public const int FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP = 1 << 7; + public const int FLAG_BIT_WRAPMODE_COLORBLENDMAP = 1 << 8; + public const int FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP = 1 << 9; + public const int FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP = 1 << 10; + public const int FLAG_BIT_WRAPMODE_MASKMAP3 = 1 << 11; + public const int FLAG_BIT_WRAPMODE_NOISE_MASKMAP = 1 << 12; + public const int FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP = 1 << 13; + public const int FLAG_BIT_WRAPMODE_BUMPTEX = 1 << 14; + public const int FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP = 1 << 15; + + // public const int FLAG_BIT_WRAPMODE2_SHAREDUV = 1 << 0; + + public const int foldOutBitMeshOption = 1 << 0; + public const int foldOutBitMainTexOption = 1 << 1; + public const int foldOutBitBaseOption = 1 << 2; + public const int foldOutBitFeatureOption = 1 << 3; + public const int foldOutBitBaseMap = 1 << 4; + public const int foldOutBitMask = 1 << 5; + public const int foldOutBitMaskMap = 1 << 6; + public const int foldOutBitMask2 = 1 << 7; + public const int foldOutBitMask3 = 1 << 8; + public const int foldOutBitTwril = 1 << 9; + public const int foldOutBitPolar = 1 << 10; + public const int foldOutBitHueShift = 1 << 11; + public const int foldOutBitSaturability = 1 << 12; + public const int foldOutBitDistanceFade = 1 << 13; + public const int foldOutBitSoftParticles = 1 << 14; + public const int foldOutBitMaskRotate = 1 << 15; + public const int foldOutBitNoise = 1 << 16; + public const int foldOutBitNoiseMap = 1 << 17; + public const int foldOutBitNoiseMaskToggle = 1 << 18; + public const int foldOutBitEmission = 1 << 19; + public const int foldOutBitDistortionChoraticaberrat = 1 << 20; + public const int foldOutDissolve = 1 << 21; + public const int foldOutDissolveMap = 1 << 22; + public const int foldOutProgramNoise = 1 << 23; + public const int foldOutDissolveRampMap = 1 << 24; + public const int foldOutDissolveMask = 1 << 25; + public const int foldOutColorBlend = 1 << 26; + public const int foldOutFresnel = 1 << 27; + public const int foldOutDepthOutline = 1 << 28; + public const int foldOutVertexOffset = 1 << 29; + public const int foldOutParallexMapping = 1 << 30; + // public const int foldOutBit1Portal= 1 << 31; + + + + + public const int foldOutBit1UVModeMainTex = 1 << 0; + public const int foldOutBit1UVModeMaskMap = 1 << 1; + public const int foldOutBit1UVModeMaskMap2 = 1 << 2; + public const int foldOutBit1UVModeMaskMap3 = 1 << 3; + public const int foldOutBit1UVModeNoiseMap = 1 << 4; + public const int foldOutBit1UVModeNoiseMaskMap = 1 << 5; + public const int foldOutBit1UVModeEmissionMap = 1 << 6; + public const int foldOutBit1UVModeDissolveMap = 1 << 7; + public const int foldOutBit1UVModeDissolveMaskMap = 1 << 8; + public const int foldOutBit1UVModeColorBlendMap = 1 << 9; + public const int foldOutBit1UVModeVertexOffsetMap = 1 << 10; + public const int foldOutBit1UVModeVertexOffsetMaskMap = 1 << 11; + public const int foldOutBit1UVModeBumpTex = 1 << 12; + public const int foldOutBit1UVModeRampColorMap = 1 << 13; + public const int foldOutBit1UVModeProgramNoise = 1 << 14; + + //留一些位置给以后可能会增加的贴图。 + public const int foldOutBit1Portal = 1 << 20; + public const int foldOutBit1ZOffset = 1 << 21; + public const int foldOutBit1CustomStencilTest = 1 << 22; + public const int foldOutBit1TaOption = 1 << 23; + public const int foldOutBit1MianTexContrast = 1 << 24; + public const int foldOutBit1VertexOffsetMask = 1 << 25; + public const int foldOutBit1MainTexColorRefine = 1 << 26; + public const int foldOutBit1LightOption = 1 << 27; + public const int foldOutBit1ShaderKeyword = 1 << 28; + public const int foldOutBit1BumpTex = 1 << 29; + + public const int foldOutBit2BumpTexToggle = 1 << 0; + public const int foldOutBit2MatCapToggle = 1 << 1; + public const int foldOutBit2RampColor = 1 << 2; + public const int foldOutBit2DissolveLine = 1 << 3; + public const int foldOutBit2BaseBackColor = 1 << 4; + public const int foldOutBit2MaskRefine = 1 << 5; + public const int foldOutBit2ScreenDistortAlphaRefine = 1 << 6; + public const int foldOutBit2ProgramNoiseSimple = 1 << 7; + public const int foldOutBit2ProgramNoiseVoronoi = 1 << 8; + public const int foldOutBit2ColorAdjustment = 1 << 9; + public const int foldOutBit2SharedUV = 1 << 10; + public const int foldOutBit2SharedUVMode = 1 << 11; + public const int foldOutBit2VAT = 1 << 12; + + + #region CustomDataCodes + + public const string CustomDataFlag0Name = "_W9ParticleCustomDataFlag0"; + public const string CustomDataFlag1Name = "_W9ParticleCustomDataFlag1"; + public const string CustomDataFlag2Name = "_W9ParticleCustomDataFlag2"; + public const string CustomDataFlag3Name = "_W9ParticleCustomDataFlag3"; + public static int CustomDataFlag0Id = Shader.PropertyToID(CustomDataFlag0Name); + public static int CustomDataFlag1Id = Shader.PropertyToID(CustomDataFlag1Name); + public static int CustomDataFlag2Id = Shader.PropertyToID(CustomDataFlag2Name); + public static int CustomDataFlag3Id = Shader.PropertyToID(CustomDataFlag3Name); + + public enum CutomDataComponent + { + Off, + CustomData1X, + CustomData1Y, + CustomData1Z, + CustomData1W, + CustomData2X, + CustomData2Y, + CustomData2Z, + CustomData2W, + UnKnownOrMixed = -1 + } + + public const int FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X = 0 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y = 1 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY = 2 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT = 3 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X = 4 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y = 5 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET = 6 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY = 7 * 4; + + public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X = 0 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y = 1 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY = 2 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_SATURATE = 3 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X = 4 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y = 5 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY = 6 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY = 7 * 4; + + public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X = 0 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y = 1 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X = 2 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y = 3 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X = 4 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y = 5 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST = 6 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME = 7 * 4; + + public const int FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X = 0 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y = 1 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X = 2 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y = 3 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X = 4 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y = 5 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X = 6 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y = 7 * 4; + + + public const int isCustomDataBit = 1 << 3; + public const int Data12Bit = 1 << 2; //true CustomData1 / false CustomData2 + public const int DataXYorZWBit = 1 << 1; //true xy / false zw + public const int DataXZorYWBit = 1 << 0; //true xz / false yw + public const int CustomData1XBit = isCustomDataBit | Data12Bit | DataXYorZWBit | DataXZorYWBit; + public const int CustomData1YBit = isCustomDataBit | Data12Bit | DataXYorZWBit; + public const int CustomData1ZBit = isCustomDataBit | Data12Bit | DataXZorYWBit; + public const int CustomData1WBit = isCustomDataBit | Data12Bit; + public const int CustomData2XBit = isCustomDataBit | DataXYorZWBit | DataXZorYWBit; + public const int CustomData2YBit = isCustomDataBit | DataXYorZWBit; + public const int CustomData2ZBit = isCustomDataBit | DataXZorYWBit; + public const int CustomData2WBit = isCustomDataBit; + + private int GetCustomDataFlagID(int dataIndex) + { + switch (dataIndex) + { + case 0: + return CustomDataFlag0Id; + + case 1: + return CustomDataFlag1Id; + + case 2: + return CustomDataFlag2Id; + case 3: + return CustomDataFlag3Id; + + } + + return 0; + } + + public string GetCustomDataFlagPropertyName(int dataIndex) + { + switch (dataIndex) + { + case 0: + return CustomDataFlag0Name; + + case 1: + return CustomDataFlag1Name; + + case 2: + return CustomDataFlag2Name; + + case 3: + return CustomDataFlag3Name; + + } + + return null; + } + + public CutomDataComponent GetCustomDataFlag(int dataBitPos, int dataIndex) + { + int bit = material.GetInteger(GetCustomDataFlagID(dataIndex)); + + bit = bit >> dataBitPos; + bit &= 15; // binary 1111 + + if ((bit & isCustomDataBit) == 0) + { + return CutomDataComponent.Off; + } + else if (bit == CustomData1XBit) + { + return CutomDataComponent.CustomData1X; + } + else if (bit == CustomData1YBit) + { + return CutomDataComponent.CustomData1Y; + } + else if (bit == CustomData1ZBit) + { + return CutomDataComponent.CustomData1Z; + } + else if (bit == CustomData1WBit) + { + return CutomDataComponent.CustomData1W; + } + else if (bit == CustomData2XBit) + { + return CutomDataComponent.CustomData2X; + } + else if (bit == CustomData2YBit) + { + return CutomDataComponent.CustomData2Y; + } + else if (bit == CustomData2ZBit) + { + return CutomDataComponent.CustomData2Z; + } + else if (bit == CustomData2WBit) + { + return CutomDataComponent.CustomData2W; + } + else + { + } + + Debug.Log("不可能存在的情况"); + return CutomDataComponent.Off; + + } + + public void SetCustomDataFlag(CutomDataComponent cutomDataComponent, int dataBitPos, int dataIndex) + { + int bit = 0; + switch (cutomDataComponent) + { + case CutomDataComponent.Off: + bit = 0; + break; + case CutomDataComponent.CustomData1X: + bit = CustomData1XBit; + break; + case CutomDataComponent.CustomData1Y: + bit = CustomData1YBit; + break; + case CutomDataComponent.CustomData1Z: + bit = CustomData1ZBit; + break; + case CutomDataComponent.CustomData1W: + bit = CustomData1WBit; + break; + case CutomDataComponent.CustomData2X: + bit = CustomData2XBit; + break; + case CutomDataComponent.CustomData2Y: + bit = CustomData2YBit; + break; + case CutomDataComponent.CustomData2Z: + bit = CustomData2ZBit; + break; + case CutomDataComponent.CustomData2W: + bit = CustomData2WBit; + break; + } + + bit = bit << dataBitPos; + int clearBit = ~(15 << dataBitPos); //~ (1111 << dataBitPos) + + int materialBit = material.GetInteger(GetCustomDataFlagID(dataIndex)); + materialBit = materialBit & clearBit; + materialBit = materialBit | bit; + material.SetInteger(GetCustomDataFlagID(dataIndex), materialBit); + } + + public bool IsCustomDataOn() + { + int prop0Flag = material.GetInteger(CustomDataFlag0Id); + int prop1Flag = material.GetInteger(CustomDataFlag1Id); + int prop2Flag = material.GetInteger(CustomDataFlag2Id); + int prop3Flag = material.GetInteger(CustomDataFlag3Id); + uint dataOnBit = 0b_1000_1000_1000_1000_1000_1000_1000_1000; //10001000100010001000100010001000; + + return ((prop0Flag & dataOnBit) > 0) || ((prop1Flag & dataOnBit) > 0) || ((prop2Flag & dataOnBit) > 0) || + ((prop3Flag & dataOnBit) > 0); + } + + bool CheckCustomData(int dataIndex, int flagIndex) + { + int flagID = 0; + switch (flagIndex) + { + case 0: + flagID = CustomDataFlag0Id; + break; + case 1: + flagID = CustomDataFlag1Id; + break; + case 2: + flagID = CustomDataFlag2Id; + break; + case 3: + flagID = CustomDataFlag3Id; + break; + } + + int flag = material.GetInteger(flagID); + int i = 0; + while (i < 8) + { + int bit = flag >> (4 * i); + if (dataIndex == 1) + { + if ((bit & 0b_1000) > 0 && (bit & 0b_0100) > 0) + { + return true; + } + } + else if (dataIndex == 2) + { + if ((bit & 0b_1000) > 0 && (bit & 0b_0100) == 0) + { + return true; + } + } + + i += 1; + } + + return false; + } + + public bool IsCustomData1On() + { + if (!IsCustomDataOn()) + { + return false; + } + + bool isCustomData1On = false; + isCustomData1On |= CheckCustomData(1, 0); + isCustomData1On |= CheckCustomData(1, 1); + isCustomData1On |= CheckCustomData(1, 2); + isCustomData1On |= CheckCustomData(1, 3); + return isCustomData1On; + } + + public bool IsCustomData2On() + { + if (!IsCustomDataOn()) + { + return false; + } + + bool isCustomData1On = false; + isCustomData1On |= CheckCustomData(2, 0); + isCustomData1On |= CheckCustomData(2, 1); + isCustomData1On |= CheckCustomData(2, 2); + isCustomData1On |= CheckCustomData(2, 3); + return isCustomData1On; + + } + + #endregion + + public const string UVModeFlag0Name = "_UVModeFlag0"; + public const string UVModeFlagType0Name = "_UVModeFlagType0"; + public static int UVModeFlag0PropID = Shader.PropertyToID(UVModeFlag0Name); + public static int UVModeFlagType0PropID = Shader.PropertyToID(UVModeFlagType0Name); + + public string GetUVModePropName(int dataIndex) + { + switch (dataIndex) + { + case 0: + return UVModeFlag0Name; + } + + return null; + } + + public enum UVMode + { + DefaultUVChannel, //0 0b_00 modeIndex 00 + SpecialUVChannel, //1 0b_01 modeIndex 00 + PolarOrTwirl, //2 0b_10 modeIndex 00 + Cylinder, //3 0b_11 modeIndex 00 + MainTex, //0 0b_00 modeIndex 01 + ScreenUV, //1 0b_01 modeIndex 01 + WorldPos, //2 0b_10 modeIndex 01 + ObjectPos, //3 0b_11 modeIndex 01 + CommonUV, //0 0b_00 modeIndex 10 + UnknownOrMixed = -1 + } + + public const int FLAG_BIT_UVMODE_POS_0_MAINTEX = 0 * 2; + public const int FLAG_BIT_UVMODE_POS_0_MASKMAP = 1 * 2; + public const int FLAG_BIT_UVMODE_POS_0_MASKMAP_2 = 2 * 2; + public const int FLAG_BIT_UVMODE_POS_0_MASKMAP_3 = 3 * 2; + public const int FLAG_BIT_UVMODE_POS_0_NOISE_MAP = 4 * 2; + public const int FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP = 5 * 2; + public const int FLAG_BIT_UVMODE_POS_0_EMISSION_MAP = 6 * 2; + public const int FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP = 7 * 2; + public const int FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP = 8 * 2; + public const int FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP = 9 * 2; + public const int FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP = 10 * 2; + public const int FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP = 11 * 2; + public const int FLAG_BIT_UVMODE_POS_0_BUMPMAP = 12 * 2; + public const int FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP = 13 * 2; + public const int FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE = 14 * 2; + public const int FLAG_BIT_UVMODE_POS_0_SHAREDUV = 15 * 2; + + public void GetUVModeFlagPropID(int flagIndex, out int flagID, out int flagTypeID) + { + switch (flagIndex) + { + case 0: + flagID = UVModeFlag0PropID; + flagTypeID = UVModeFlagType0PropID; + return; + } + + flagID = 0; + flagTypeID = 0; + + } + + public void SetUVMode(UVMode mode, int uvModePos, int flagIndex = 0) + { + GetUVModeFlagPropID(flagIndex, out int uvModeFlagPropId, out int uvModeFlagTypePropId); + int uvModeFlag = material.GetInteger(uvModeFlagPropId); + int uvModeFlagType = material.GetInteger(uvModeFlagTypePropId); + + + int clearFlag = 0b_11 << uvModePos; + clearFlag = ~ clearFlag; + + uvModeFlag &= clearFlag; + int modeBit = (int)mode % 4 << uvModePos; + uvModeFlag |= modeBit; + uvModeFlagType &= clearFlag; + int typeBit = (int)mode / 4 << uvModePos; + uvModeFlagType |= typeBit; + + material.SetInteger(uvModeFlagPropId, uvModeFlag); + material.SetInteger(uvModeFlagTypePropId, uvModeFlagType); + } + + public UVMode GetUVMode(int uvModePos, int flagIndex = 0) + { + GetUVModeFlagPropID(flagIndex, out int uvModeFlagPropId, out int uvModeFlagTypePropId); + int uvModeFlag = material.GetInteger(uvModeFlagPropId); + uvModeFlag = uvModeFlag >> uvModePos; + uvModeFlag &= 0b_11; + int uvModeFlagType = material.GetInteger(uvModeFlagTypePropId); + uvModeFlagType = uvModeFlagType >> uvModePos; + uvModeFlagType &= 0b_11; + return (UVMode)(uvModeFlag + 4 * uvModeFlagType); + } + + public bool CheckIsUVModeOn(UVMode mode) + { + uint uvModeFlag0 = (uint)material.GetInteger(UVModeFlag0PropID); + uint uvModeFlagType0 = (uint)material.GetInteger(UVModeFlagType0PropID); + + uint uvModeflagBit = (uint)mode % 4; + uint uvModeflagTypeBit = (uint)mode / 4; + + bool isUvMode = false; + for (int i = 0; i < 16; i++) + { + uint checkflagBit = uvModeFlag0 >> (i * 2); + checkflagBit = checkflagBit & 0b_11; + uint checkflagTypeBit = uvModeflagTypeBit >> (i * 2); + checkflagTypeBit = checkflagTypeBit & 0b_11; + if (checkflagBit == uvModeflagBit && checkflagTypeBit == uvModeflagTypeBit) + { + isUvMode = true; + break; + } + } + + return isUvMode; + } + + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA = 0 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1 = 1 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2 = 2 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3 = 3 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK = 4 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP = 5 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP = 6 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP = 7 * 2; + + + public enum ColorChannel + { + X, + Y, + Z, + W, + UnKnownOrMixedValue + } + + public void SetColorChanel(ColorChannel channel, int colorChannelFlagPos) + { + int colorChannelFlag = material.GetInteger(colorChannelFlagId); + + int clearFlag = 0b_11 << colorChannelFlagPos; + clearFlag = ~ clearFlag; + + colorChannelFlag &= clearFlag; + int channelBit = (int)channel << colorChannelFlagPos; + colorChannelFlag |= channelBit; + + material.SetInteger(colorChannelFlagId, colorChannelFlag); + } + + public ColorChannel GetColorChanel(int colorChannelFlagPos) + { + int colorChannelFlag = material.GetInteger(colorChannelFlagId); + colorChannelFlag = colorChannelFlag >> colorChannelFlagPos; + colorChannelFlag &= 0b_11; + return (ColorChannel)colorChannelFlag; + } + + public const int FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND = 0 * 3; + public const int FLAG_BIT_PNOISE_BLEND_POS_0_MASK = 1 * 3; + public const int FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE = 2 * 3; + public const int FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT = 3 * 3; + public const int FLAG_BIT_PNOISE_BLEND_POS_0_MAINTEX = 4 * 3; + + public enum PNoiseBlendMode + { + NotUse = 0, + Multiply = 1, + Min = 2, + HardLight = 3, + UnKnownOrMixedValue = -1 + + //后续看看要不要更多吧 + } + + public void SetPNoiseBlendMode(PNoiseBlendMode mode, int pNoiseBlendModeFlagPos) + { + int pNoiseBlendFlag = material.GetInteger(pNoiseBlendFlagId); + int blendMode = (int)mode; + if (blendMode < 0) return; + int clearFlag = 0b_111 << pNoiseBlendModeFlagPos; + clearFlag = ~clearFlag; + pNoiseBlendFlag &= clearFlag; + int pNoiseBlendBit = blendMode << pNoiseBlendModeFlagPos; + //先不考虑超过4个选项(2bit)的情况 + pNoiseBlendFlag |= pNoiseBlendBit; + material.SetInteger(pNoiseBlendFlagId, pNoiseBlendFlag); + } + + public PNoiseBlendMode GetPNoiseBlendMode(int pNoiseBlendModeFlagPos) + { + int pNoiseBlendFlag = material.GetInteger(pNoiseBlendFlagId); + pNoiseBlendFlag = pNoiseBlendFlag >> pNoiseBlendModeFlagPos; + pNoiseBlendFlag &= 0b_111; + //先不考虑超过4个选项(2bit)的情况 + return (PNoiseBlendMode)pNoiseBlendFlag; + } + + } +} diff --git a/Packages/NB_FX/NBShaders/Runtime/W9ParticleShaderFlags.cs.meta b/Packages/NB_FX/NBShaders/Runtime/W9ParticleShaderFlags.cs.meta new file mode 100644 index 00000000..be8e6638 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Runtime/W9ParticleShaderFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b13c8a972207b57458dd444106acbf3a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Runtime/com.xuanxuan.nb.shaders.asmdef b/Packages/NB_FX/NBShaders/Runtime/com.xuanxuan.nb.shaders.asmdef new file mode 100644 index 00000000..5d255961 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Runtime/com.xuanxuan.nb.shaders.asmdef @@ -0,0 +1,16 @@ +{ + "name": "com.xuanxuan.nb.shaders", + "rootNamespace": "", + "references": [ + "GUID:8f9e4d586616f13449cfeb86c5f704c2" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/NB_FX/NBShaders/Runtime/com.xuanxuan.nb.shaders.asmdef.meta b/Packages/NB_FX/NBShaders/Runtime/com.xuanxuan.nb.shaders.asmdef.meta new file mode 100644 index 00000000..6b5d9b1c --- /dev/null +++ b/Packages/NB_FX/NBShaders/Runtime/com.xuanxuan.nb.shaders.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0e3b0e6ce60c7a34094f8f9822c0b7f2 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Shader.meta b/Packages/NB_FX/NBShaders/Shader.meta new file mode 100644 index 00000000..d35795a3 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5fdc89efbf4a9bf4c9449cc01f16d08a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Shader/HLSL.meta b/Packages/NB_FX/NBShaders/Shader/HLSL.meta new file mode 100644 index 00000000..aaf3843f --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/HLSL.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 944a1679494774748b2936893c18c9ce +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Shader/HLSL/EffectFlags.hlsl b/Packages/NB_FX/NBShaders/Shader/HLSL/EffectFlags.hlsl new file mode 100644 index 00000000..cda7e4f1 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/HLSL/EffectFlags.hlsl @@ -0,0 +1,324 @@ +#ifndef EFFECT_FLAGS +#define EFFECT_FLAGS + + #define FLAG_BIT_SATURABILITY_ON (1 << 0) + #define FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE (1 << 1) + #define FLAG_BIT_PARTICLE_FRESNEL_FADE_ON (1 << 2) + #define FLAG_BIT_PARTICLE_FRESNEL_COLOR_ON (1 << 3) + #define FLAG_BIT_PARTICLE_USETEXCOORD2 (1 << 4) + #define FLAG_BIT_PARTICLE_DISTANCEFADE_ON (1 << 5) + #define FLAG_BIT_PARTICLE_CHORATICABERRAT (1 << 6) + #define FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON (1 << 7) + #define FLAG_BIT_PARTICLE_POLARCOORDINATES_ON (1 << 8) + #define FLAG_BIT_PARTICLE_UTWIRL_ON (1 << 9) + #define FLAG_BIT_PARTICLE_LINEARTOGAMMA_ON (1 << 10) + #define FLAG_BIT_PARTICLE_FRESNEL_ON (1 << 11) + #define FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON (1 << 12) + #define FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA (1 << 13) + #define FLAG_BIT_PARTICLE_UIEFFECT_ON (1 << 14) + #define FLAG_BIT_PARTICLE_UNSCALETIME_ON (1 << 15) + #define FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON (1 << 16) + #define FLAG_BIT_PARTICLE_CUSTOMDATA1_ON (1 << 17) + #define FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON (1 << 18) + #define FLAG_BIT_HUESHIFT_ON (1 << 19) + #define FLAG_BIT_PARTICLE_CUSTOMDATA2_ON (1 << 20) + #define FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE (1 << 21) + #define FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX (1 << 22) + #define FLAG_BIT_PARTICLE_RAMP_COLOR_MAP_MODE_ON (1 << 23) + #define FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD (1 << 24) + #define FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE (1 << 25) + #define FLAG_BIT_PARTICLE_DISSOLVE_RAMP_MAP (1 << 26) + #define FLAG_BIT_PARTICLE_DISSOLVE_MASK (1 << 27) + #define FLAG_BIT_PARTICLE_BACKCOLOR (1 << 28) + #define FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA (1 << 29) + #define FLAG_BIT_PARTICLE_VERTEX_OFFSET_ON (1 << 30) + #define FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR (1 << 31) + // uint _W9ParticleShaderFlags; + + #define FLAG_BIT_PARTICLE_1_DEPTH_OUTLINE (1 << 0) + #define FLAG_BIT_PARTICLE_1_PARALLAX_MAPPING (1 << 1) + #define FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT (1 << 2) + #define FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT (1 << 3) + #define FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT (1 << 4) + #define FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK (1 << 5) + #define FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY (1 << 6) + #define FLAG_BIT_PARTICLE_1_MASK_REFINE (1 << 7) + #define FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE (1 << 8) + #define FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR (1 << 9) + #define FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE (1 << 10) + #define FLAG_BIT_PARTICLE_1_DISSOVLE_USE_RAMP (1 << 11) + #define FLAG_BIT_PARTICLE_1_MASK_MAP2 (1 << 12) + #define FLAG_BIT_PARTICLE_1_MASK_MAP3 (1 << 13) + #define FLAG_BIT_PARTICLE_1_NOISE_MASKMAP (1 << 14) + #define FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER (1 << 15) + #define FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI (1 << 16) + #define FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE (1 << 17) + #define FLAG_BIT_PARTICLE_1_USE_TEXCOORD1 (1 << 18) + #define FLAG_BIT_PARTICLE_1_USE_TEXCOORD2 (1 << 19) + #define FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE (1 << 20) + #define FLAG_BIT_PARTICLE_1_UV_FROM_MESH (1 << 21) + #define FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE (1 << 22) + #define FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM (1 << 23) + #define FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST (1 << 24) + #define FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO (1 << 25) + #define FLAG_BIT_PARTICLE_1_VERTEXOFFSET_MASKMAP (1 << 26) + #define FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE (1 << 27) + #define FLAG_BIT_PARTICLE_1_BUMP_TEX_UV_FOLLOW_MAINTEX (1 << 28) + #define FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP (1 << 29) + #define FLAG_BIT_PARTICLE_1_MATCAP_MULTY_MODE (1 << 30) + + + //WrapMode不能够超过16位(因为会占用x和x+16两个bit位) + #define FLAG_BIT_WRAPMODE_BASEMAP (1 << 0) + #define FLAG_BIT_WRAPMODE_MASKMAP (1 << 1) + #define FLAG_BIT_WRAPMODE_MASKMAP2 (1 << 2) + #define FLAG_BIT_WRAPMODE_NOISEMAP (1 << 3) + #define FLAG_BIT_WRAPMODE_EMISSIONMAP (1 << 4) + #define FLAG_BIT_WRAPMODE_DISSOLVE_MAP (1 << 5) + #define FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP (1 << 6) + #define FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP (1 << 7) + #define FLAG_BIT_WRAPMODE_COLORBLENDMAP (1 << 8) + #define FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP (1 << 9) + #define FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP (1 << 10) + #define FLAG_BIT_WRAPMODE_MASKMAP3 (1 << 11) + #define FLAG_BIT_WRAPMODE_NOISE_MASKMAP (1 << 12) + #define FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP (1 << 13) + #define FLAG_BIT_WRAPMODE_BUMPTEX (1 << 14) + #define FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP (1 << 15) + + #define FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X (0*4) + #define FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y (1*4) + #define FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY (2*4) + #define FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT (3*4) + #define FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X (4*4) + #define FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y (5*4) + #define FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET (6*4) + #define FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY (7*4) + + #define FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X (0*4) + #define FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y (1*4) + #define FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY (2*4) + #define FLAGBIT_POS_1_CUSTOMDATA_SATURATE (3*4) + #define FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X (4*4) + #define FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y (5*4) + #define FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY (6*4) + #define FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY (7*4) + + #define FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X (0*4) + #define FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y (1*4) + #define FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X (2*4) + #define FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y (3*4) + #define FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X (4*4) + #define FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y (5*4) + #define FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST (6*4) + #define FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME (7*4) + + #define FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X (0*4) + #define FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y (1*4) + #define FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X (2*4) + #define FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y (3*4) + #define FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X (4*4) + #define FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y (5*4) + #define FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X (6*4) + #define FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y (7*4) + + #define isCustomDataBit (1 << 3) + #define Data12Bit (1 << 2) + #define DataXYorZWBit (1 << 1) + #define DataXZorYWBit (1 << 0) + + #define FLAG_BIT_UVMODE_POS_0_MAINTEX (0*2) + #define FLAG_BIT_UVMODE_POS_0_MASKMAP (1*2) + #define FLAG_BIT_UVMODE_POS_0_MASKMAP_2 (2*2) + #define FLAG_BIT_UVMODE_POS_0_MASKMAP_3 (3*2) + #define FLAG_BIT_UVMODE_POS_0_NOISE_MAP (4*2) + #define FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP (5*2) + #define FLAG_BIT_UVMODE_POS_0_EMISSION_MAP (6*2) + #define FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP (7*2) + #define FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP (8*2) + #define FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP (9*2) + #define FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP (10*2) + #define FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP (11*2) + #define FLAG_BIT_UVMODE_POS_0_BUMPTEX (12*2) + #define FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP (13*2) + #define FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE (14*2) + #define FLAG_BIT_UVMODE_POS_0_SHAREDUV (15*2) + + #define FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA (0*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1 (1*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2 (2*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3 (3*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK (4*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP (5*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP (6*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP (7*2) + + float GetCustomData(uint flagProperty,int flagPos,float orignValue,half4 cutstomData1,half4 customData2) + { + uint bit = flagProperty >> flagPos; + + // bit &= 15;// binary 1111 这一步可能是没必要的。 + UNITY_BRANCH + if((bit & isCustomDataBit) == 0) + { + return orignValue; + } + else + { + half4 customData = 0; + if((bit & Data12Bit)) + { + customData = cutstomData1; + + } + else + { + customData = customData2; + } + + if(bit & DataXYorZWBit) + { + if(bit & DataXZorYWBit) + { + return customData.x; + } + else + { + return customData.y; + } + } + else + { + if(bit & DataXZorYWBit) + { + return customData.z; + } + else + { + return customData.w; + } + } + } + return 999;//提示错误 + } + + + struct BaseUVs + { + float2 defaultUVChannel; + float2 specialUVChannel; + float2 uvAfterTwirlPolar; + float2 cylinderUV; + float2 mainTexUV; + float2 screenUV; + float2 worldPosUV; + float2 objectPosUV; + float2 sharedUV; + }; + + float2 GetUVByUVMode(uint flagProperty,uint flagTypeProperty,int flagPos,BaseUVs baseUVs) + { + flagProperty = flagProperty >> flagPos; + flagProperty &= 3; + flagTypeProperty = flagTypeProperty >> flagPos; + flagTypeProperty &= 3; + switch (flagTypeProperty) + { + case 0: + switch(flagProperty) + { + case 0: + return baseUVs.defaultUVChannel; + case 1: + return baseUVs.specialUVChannel; + case 2: + return baseUVs.uvAfterTwirlPolar; + case 3: + return baseUVs.cylinderUV; + default: + return baseUVs.defaultUVChannel; + } + case 1: + switch(flagProperty) + { + case 0: + return baseUVs.mainTexUV; + case 1: + return baseUVs.screenUV; + case 2: + return baseUVs.worldPosUV; + case 3: + return baseUVs.objectPosUV; + default: + return baseUVs.defaultUVChannel; + } + case 2: + switch(flagProperty) + { + case 0: + return baseUVs.sharedUV; + default: + return baseUVs.defaultUVChannel; + } + default: + return baseUVs.defaultUVChannel; + } + } + + half Blend_HardLight(half Base, half Blend) + { + half result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend); + half result2 = 2.0 * Base * Blend; + half zeroOrOne = step(Blend, 0.5); + half Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1; + return Out; + } + + #define FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND (0*3) + #define FLAG_BIT_PNOISE_BLEND_POS_0_MASK (1*3) + #define FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE (2*3) + #define FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT (3*3) + #define FLAG_BIT_PNOISE_BLEND_POS_0_MAINTEX (4*3) + + half BlendPNoise(uint flagProperty,int flagPos,half source,half pNoise,half opacity) + { + flagProperty = flagProperty >> flagPos; + flagProperty &= 7; + switch(flagProperty) + { + case 0: + return source; + case 1: + return lerp(source,pNoise*source,opacity); + case 2: + return lerp(source,min(pNoise,source),opacity); + case 3: + return lerp(source,Blend_HardLight(source,pNoise),opacity); + default: + return source; + } + } + + //ForDistort + half2 BlendPNoise(uint flagProperty,int flagPos,half2 source,half2 pNoise,half opacity) + { + flagProperty = flagProperty >> flagPos; + flagProperty &= 7; + switch(flagProperty) + { + case 0: + return source; + case 1: + return lerp(source,pNoise*source,opacity); + case 2: + return lerp(source,min(pNoise,source),opacity); + case 3: + return lerp(source,Blend_HardLight(source,pNoise),opacity); + default: + return source; + } + } + + + +#endif diff --git a/Packages/NB_FX/NBShaders/Shader/HLSL/EffectFlags.hlsl.meta b/Packages/NB_FX/NBShaders/Shader/HLSL/EffectFlags.hlsl.meta new file mode 100644 index 00000000..770e62c6 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/HLSL/EffectFlags.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4918b275ae4dce948a5cedc6f3612066 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitForwardPassNew.hlsl b/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitForwardPassNew.hlsl new file mode 100644 index 00000000..8ee28b72 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitForwardPassNew.hlsl @@ -0,0 +1,1239 @@ +#ifndef PARTICLESUNLITFORWARDPASS + #define PARTICLESUNLITFORWARDPASS + #include "ParticlesUnlitInputNew.hlsl" + #include "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl" + #include "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl" + + #if defined(NB_DEPTH_ONLY_PASS) || defined(NB_SHADOW_CASTER_PASS) + #define NB_DEPTH_SHADOW_PASS + #endif + + #if defined(NB_SHADOW_CASTER_PASS) + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" + float3 _LightDirection; + float3 _LightPosition; + #endif + + + /////////////////////////////////////////////////////////////////////////////// + // Vertex and Fragment functions // + + + VaryingsParticle vertParticleUnlit(AttributesParticle input) + { + VaryingsParticle output = (VaryingsParticle)0; + + output.VaryingsP_Custom1 = input.Custom1; + output.VaryingsP_Custom2 = input.Custom2; + + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + time = _Time.y; + + float4 positionOS = input.vertex; + float3 normalOS = input.normalOS; + #if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) || defined(_FX_LIGHT_MODE_SIX_WAY) + float4 tangentOS = input.tangentOS; + #endif + #ifdef _CUSTOM_LOCAL_TRANSFORM + positionOS.xyz = TransformWorldToObject_NB(input.vertex.xyz); + normalOS = TransformWorldToObjectNormal_NB(input.normalOS); + #if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) || defined(_FX_LIGHT_MODE_SIX_WAY) + tangentOS.xyz = TransformWorldToObjectDir_NB(input.tangentOS.xyz); + #endif + #endif + ApplyVAT(input, positionOS, normalOS); + // position ws is used to compute eye depth in vertFading + output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz); + output.positionOS.xyz = positionOS; + + output.clipPos = TransformObjectToHClip_NB(positionOS.xyz); + + float unityFogFactor = ComputeFogFactor(output.clipPos.z); + + output.positionWS.w = unityFogFactor; + + output.color = TryLinearize(input.color); + + // output.viewDirWS = GetWorldSpaceNormalizeViewDir(output.positionWS.xyz); + output.normalWSAndAnimBlend.xyz = TransformObjectToWorldNormal_NB(normalOS.xyz); + + #if defined(_PARALLAX_MAPPING)||defined(_NORMALMAP)||defined(_FX_LIGHT_MODE_SIX_WAY) + real sign = tangentOS.w * GetCustomLocalOddNegativeScale(); + half3 tangentWS = TransformObjectToWorldDir_NB(tangentOS.xyz); + output.tangentWS = half4(tangentWS,sign); + #endif + + + #ifndef _FX_LIGHT_MODE_UNLIT + #ifdef _FX_LIGHT_MODE_SIX_WAY + float3 bitangent = sign * cross(output.normalWSAndAnimBlend.xyz, output.tangentWS.xyz); + // GetSixWayBakeDiffuseLight(output.normalWSAndAnimBlend.xyz,output.tangentWS,bitangent, + // output.bakeDiffuseLighting0,output.bakeDiffuseLighting1,output.bakeDiffuseLighting2, + // output.backBakeDiffuseLighting0,output.backBakeDiffuseLighting1,output.backBakeDiffuseLighting2); + + GetSixWayBakeDiffuseLight(output.normalWSAndAnimBlend.xyz,output.tangentWS,bitangent, + output.bakeDiffuseLighting0,output.bakeDiffuseLighting1,output.bakeDiffuseLighting2, + output.backBakeDiffuseLighting0,output.backBakeDiffuseLighting1,output.backBakeDiffuseLighting2); + + #else + OUTPUT_SH(output.normalWSAndAnimBlend.xyz, output.vertexSH); + #ifdef _ADDITIONAL_LIGHTS_VERTEX + output.vertexLight = VertexLighting(output.positionWS.xyz, output.normalWSAndAnimBlend.xyz); + #endif + #endif + #endif + + + + // UNITY_FLATTEN + // if(CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_ON)) + // { + // output.fresnelViewDir = output.viewDirWS; + // } + + output.texcoord.xy = input.texcoords.xy; + + //顶点处理的原则: + //Twirl和极坐标,贴花处理,在片段着色器层处理UV。 + //BaseMap,遮罩Mask,Noise,高光(自发光) 和极坐标处理相关。 + BaseUVs baseUVs; + if(!isProcessUVInFrag()) + { + + float2 specialUVInTexcoord3 = 0; + //如果同时在粒子系统里开启序列帧融帧和特殊UV通道模式。 + #if _FLIPBOOKBLENDING_ON + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD1)|CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2))) + { + specialUVInTexcoord3 = input.texcoordBlend.yz; + output.texcoord2AndSpecialUV.zw = specialUVInTexcoord3; + } + #endif + ParticleUVs particleUVs = (ParticleUVs)0; + float2 screenUV = output.clipPos.xy/output.clipPos.w; + screenUV = screenUV*0.5+0.5; + baseUVs = ProcessBaseUVs(input.texcoords,specialUVInTexcoord3,output.VaryingsP_Custom1,output.VaryingsP_Custom2,output.positionOS.xyz,output.positionWS,screenUV); + ParticleProcessUV(particleUVs,input.texcoords,output.VaryingsP_Custom1,output.VaryingsP_Custom2,baseUVs); + output.texcoord2AndSpecialUV.xy = particleUVs.animBlendUV; + output.texcoord2AndSpecialUV.zw= particleUVs.specUV; + output.texcoord.xy = particleUVs.mainTexUV; + output.texcoord.zw = particleUVs.maskMapUV; + + output.texcoordMaskMap2.xy = particleUVs.maskMap2UV; + output.texcoordMaskMap2.zw = particleUVs.maskMap3UV; + #if defined (_NORMALMAP) || defined(_COLOR_RAMP) + output.bumpTexAndColorRampMapTexcoord.xy = particleUVs.bumpTexUV; + output.bumpTexAndColorRampMapTexcoord.zw = particleUVs.colorRampMapUV; + + #endif + + #if defined (_EMISSION) || defined(_COLORMAPBLEND) + output.emissionColorBlendTexcoord.xy = particleUVs.emissionUV; + output.emissionColorBlendTexcoord.zw = particleUVs.colorBlendUV; + #endif + + #ifdef _NOISEMAP + output.noisemapTexcoord.xy = particleUVs.noiseMapUV; + output.noisemapTexcoord.zw = particleUVs.noiseMaskMapUV; + #endif + #if defined(_DISSOLVE) + output.dissolveTexcoord.xy = particleUVs.dissolve_uv; + output.dissolveTexcoord.zw = particleUVs.dissolve_mask_uv; + #endif + + #ifdef _PROGRAM_NOISE + output.dissolveNoiseTexcoord.xy = particleUVs.dissolve_noise1_UV; + output.dissolveNoiseTexcoord.zw = particleUVs.dissolve_noise2_UV; + #endif + } + else + { + output.texcoord = input.texcoords; + #if _FLIPBOOKBLENDING_ON + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)) + { + output.texcoord2AndSpecialUV.zw = input.texcoordBlend.yz; + } + #endif + } + #ifdef _FLIPBOOKBLENDING_ON + //粒子帧融合的情况,兼容一下。 + output.normalWSAndAnimBlend.w = input.texcoordBlend.x; + #endif + + if(CheckLocalFlags(FLAG_BIT_PARTICLE_VERTEX_OFFSET_ON)) + { + BaseUVs baseUVsForVertexOffset; + if(!isProcessUVInFrag()) + { + baseUVsForVertexOffset = baseUVs; + } + else + { + float2 screenUV = output.clipPos.xy/output.clipPos.w; + screenUV = screenUV*0.5+0.5; + baseUVsForVertexOffset = ProcessBaseUVs(input.texcoords,0,output.VaryingsP_Custom1,output.VaryingsP_Custom2,positionOS,output.positionWS,screenUV); + } + + //因为极坐标和旋转会强制到Frag计算,所以顶点在这边特殊处理一遍。 + + _VertexOffset_Map_ST.z += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X,0,input.Custom1,input.Custom2); + _VertexOffset_Map_ST.w += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y,0,input.Custom1,input.Custom2); + _VertexOffset_Vec.z = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY,_VertexOffset_Vec.z,input.Custom1,input.Custom2); + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_VERTEXOFFSET_MASKMAP)) + { + _VertexOffset_MaskMap_ST.z += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X,0,input.Custom1,input.Custom2); + _VertexOffset_MaskMap_ST.w += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y,0,input.Custom1,input.Custom2); + } + + float2 vertexOffsetUVs = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP,baseUVsForVertexOffset); + float2 vertexOffsetMaskUVs = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP,baseUVsForVertexOffset); + + half3 vertexOffsetOS = 0; + positionOS.xyz = VetexOffset(positionOS,vertexOffsetUVs,vertexOffsetMaskUVs,normalOS,vertexOffsetOS); + #ifdef NB_DEBUG_VERTEX_OFFSET + half3 vertexOffsetWS = TransformObjectToWorldDir_NB(vertexOffsetOS,false); + output.color = half4(abs(vertexOffsetWS),1); + #endif + output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz); + + //再算一遍 + output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz); + output.positionOS.xyz = positionOS; + output.clipPos = TransformObjectToHClip_NB(positionOS.xyz); + } + + #if defined(NB_SHADOW_CASTER_PASS) + #if _CASTING_PUNCTUAL_LIGHT_SHADOW + float3 lightDirectionWS = normalize(_LightPosition - output.positionWS.xyz); + #else + float3 lightDirectionWS = _LightDirection; + #endif + + output.clipPos = TransformWorldToHClip(ApplyShadowBias(output.positionWS.xyz, output.normalWSAndAnimBlend.xyz, lightDirectionWS)); + + #if UNITY_REVERSED_Z + output.clipPos.z = min(output.clipPos.z, UNITY_NEAR_CLIP_VALUE); + #else + output.clipPos.z = max(output.clipPos.z, UNITY_NEAR_CLIP_VALUE); + #endif + #endif + + #if !defined(NB_DEPTH_SHADOW_PASS) + UNITY_BRANCH + if(needEyeDepth()) + { + float4 ndc = output.clipPos*0.5f; + output.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w; + output.positionNDC.zw = output.clipPos.zw; + } + #endif + + return output; + } + + + #if defined(NB_SHADOW_CASTER_PASS) + uint NBShadowBayer2(uint x, uint y) + { + return (((x ^ y) & 1u) << 1) | (y & 1u); + } + + half NBShadowDitherMaskClip(float4 positionCS, half alpha) + { + // Built-in Standard Particle uses a 4x4x16 dither mask texture. + uint x = (uint)positionCS.x & 3u; + uint y = (uint)positionCS.y & 3u; + uint bayer = NBShadowBayer2(x & 1u, y & 1u) * 4u + NBShadowBayer2((x >> 1) & 1u, (y >> 1) & 1u); + half coverage = floor(saturate(alpha) * 16.0); + return coverage - (half)bayer - 0.01; + } + #endif + + ///////////////////////Fragment functions //////////////////////// + + half4 fragParticleUnlit(VaryingsParticle input, half facing : VFACE): SV_Target + { + #if !defined(NB_DEPTH_SHADOW_PASS) + float3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS.xyz); + input.normalWSAndAnimBlend.xyz = facing > 0 ? input.normalWSAndAnimBlend.xyz : -input.normalWSAndAnimBlend.xyz; + #endif + + + UNITY_SETUP_INSTANCE_ID(input); + #if !defined(NB_DEPTH_SHADOW_PASS) + #ifdef NB_DEBUG_VERTEX_OFFSET + return input.color; + #endif + #endif + + time = _Time.y; + + float2 screenUV = input.clipPos.xy / _ScaledScreenParams.xy; + + #if !defined(NB_DEPTH_SHADOW_PASS) + + real sceneZBufferDepth = 0; + real sceneZ = 0; + + UNITY_BRANCH + if(needSceneDepth()) + { + #if UNITY_REVERSED_Z + sceneZBufferDepth = SampleSceneDepth(screenUV); + #else + // Adjust z to match NDC for OpenGL + sceneZBufferDepth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(screenUV)); + #endif + sceneZ = (unity_OrthoParams.w == 0) ? LinearEyeDepth(sceneZBufferDepth, _ZBufferParams) : LinearDepthToEyeDepth(sceneZBufferDepth);//场景当前深度 + } + + real thisZ = 0; + + + half3 positionVS = 0; + if(needPositionVS()) + { + positionVS = TransformWorldToView(input.positionWS); + } + + if(needEyeDepth()) + { + thisZ = (unity_OrthoParams.w == 0) ? LinearEyeDepth(input.positionNDC.z / input.positionNDC.w, _ZBufferParams) : -positionVS.z;//场景当前深度 + } + + + #ifdef _DEPTH_DECAL + float3 fragWorldPos = ComputeWorldSpacePosition(screenUV, sceneZBufferDepth, UNITY_MATRIX_I_VP); + float3 fragobjectPos = TransformWorldToObject_NB(fragWorldPos); + + float3 absFragObjectPos = abs(fragobjectPos); + half clipValue = step(absFragObjectPos.x,0.5); + clipValue *= step(absFragObjectPos.y,0.5); + clipValue *= step(absFragObjectPos.z,0.5); + half decalAlpha = NB_Remap (abs(fragobjectPos.y),0.1,0.5,1,0); + decalAlpha = decalAlpha*decalAlpha; + decalAlpha *= clipValue; + float2 decalUV = fragobjectPos.xz + 0.5; + #endif + #endif + + float4 uv = input.texcoord; + #if !defined(NB_DEPTH_SHADOW_PASS) + #ifdef _DEPTH_DECAL + uv.xy = decalUV; + #endif + #endif + + float2 MainTex_UV; + float3 blendUv; + blendUv.xy = input.texcoord2AndSpecialUV.xy; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) + { + blendUv.z = _AnimationSheetHelperBlendIntensity; + } + else + { + blendUv.z = input.normalWSAndAnimBlend.w; + } + float2 MaskMapuv; + float2 MaskMapuv2; + float2 MaskMapuv3; + float2 noiseMap_uv; + float2 noiseMaskMap_uv; + float2 colorBlendMap_uv; + float2 emission_uv; + float2 dissolve_uv; + float2 dissolve_mask_uv; + float4 dissolve_noise_uv; + float2 BumpTex_uv; + float2 colorRamp_uv; + + //如果同时在粒子系统里开启序列帧融帧和特殊UV通道模式。 + + if(isProcessUVInFrag()) + { + float2 specialUVInTexcoord3 = 0; + #if _FLIPBOOKBLENDING_ON + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2))) + { + specialUVInTexcoord3 = input.texcoord2AndSpecialUV.zw; + } + + #endif + ParticleUVs particleUVs = (ParticleUVs)0; + BaseUVs baseUVs = ProcessBaseUVs(uv,specialUVInTexcoord3,input.VaryingsP_Custom1,input.VaryingsP_Custom2,input.positionOS.xyz,input.positionWS.xyz,screenUV); + ParticleProcessUV(particleUVs,uv,input.VaryingsP_Custom1,input.VaryingsP_Custom2,baseUVs); + MainTex_UV.xy = particleUVs.mainTexUV; + blendUv.xy = particleUVs.animBlendUV; + MaskMapuv = particleUVs.maskMapUV; + MaskMapuv2 = particleUVs.maskMap2UV; + MaskMapuv3 = particleUVs.maskMap3UV; + emission_uv = particleUVs.emissionUV; + dissolve_uv = particleUVs.dissolve_uv; + dissolve_mask_uv = particleUVs.dissolve_mask_uv; + colorBlendMap_uv = particleUVs.colorBlendUV; + noiseMap_uv = particleUVs.noiseMapUV; + noiseMaskMap_uv = particleUVs.noiseMaskMapUV; + dissolve_noise_uv = float4(particleUVs.dissolve_noise1_UV,particleUVs.dissolve_noise2_UV); + BumpTex_uv = particleUVs.bumpTexUV; + colorRamp_uv = particleUVs.colorRampMapUV; + } + else + { + MainTex_UV = input.texcoord.xy; + MaskMapuv = input.texcoord.zw; + MaskMapuv2 = input.texcoordMaskMap2.xy; + MaskMapuv3 = input.texcoordMaskMap2.zw; + + #if defined (_NORMALMAP)||defined(_COLOR_RAMP) + BumpTex_uv = input.bumpTexAndColorRampMapTexcoord.xy; + colorRamp_uv = input.bumpTexAndColorRampMapTexcoord.zw; + #endif + + #ifdef _NOISEMAP + noiseMap_uv = input.noisemapTexcoord.xy; + noiseMaskMap_uv = input.noisemapTexcoord.zw; + #endif + + #if defined (_EMISSION) || defined(_COLORMAPBLEND) + emission_uv = input.emissionColorBlendTexcoord.xy; + colorBlendMap_uv = input.emissionColorBlendTexcoord.zw; + #endif + + #ifdef _DISSOLVE + dissolve_uv = input.dissolveTexcoord.xy; + dissolve_mask_uv = input.dissolveTexcoord.zw; + #endif + #ifdef _PROGRAM_NOISE + dissolve_noise_uv = input.dissolveNoiseTexcoord; + #endif + } + + + half programNoise; + #ifdef _PROGRAM_NOISE + half programSimpleNoise; + half programVoronoiNoise; + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE)) + { + programSimpleNoise = SimplexNoise(dissolve_noise_uv.xy,_Time.y*_DissolveVoronoi_Vec2.z); + programNoise = programSimpleNoise; + } + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI)) + { + half cell; + Unity_Voronoi_float(dissolve_noise_uv.zw,_Time.y*_DissolveVoronoi_Vec2.w,1,programVoronoiNoise,cell); + programNoise = programVoronoiNoise ; + } + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE)&CheckLocalFlags1(FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI)) + { + programNoise = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND,programSimpleNoise,programVoronoiNoise,_ProgramNoiseBaseBlendOpacity); + // Unity_Blend_HardLight_half(programSimpleNoise,programVoronoiNoise,_DissolveVoronoi_Vec2.x,programNoise); + } + + // half dissolveSample = dissolveValue; + // Unity_Blend_HardLight_half(overlayVoroni,dissolveSample,_DissolveVoronoi_Vec2.y,dissolveValue); + #ifdef NB_DEBUG_PNOISE + return half4(programNoise.xxx,1); + #endif + + #endif + + half2 originUV = MainTex_UV; + + //预先处理好法线贴图部分 + half metallic = 1; + half smoothness = 1; + half3 normalTS = half3(0, 0, 1);//TODO + half3x3 tangentToWorld = (half3x3)0; + #if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) + float sgn = input.tangentWS.w; // should be either +1 or -1 + float3 bitangent = sgn * cross(input.normalWSAndAnimBlend.xyz, input.tangentWS.xyz); + tangentToWorld = half3x3(input.tangentWS.xyz, bitangent.xyz, input.normalWSAndAnimBlend.xyz); + #endif + #ifdef _PARALLAX_MAPPING + float3 tangentViewDir = TransformWorldToTangentDir(viewDirWS, tangentToWorld, true); + MainTex_UV.xy = ParallaxOcclusionMapping(MainTex_UV, tangentViewDir); + #endif + #ifdef _NORMALMAP + half4 normalMapSample = SampleTexture2DWithWrapFlags(_BumpTex,BumpTex_uv,FLAG_BIT_WRAPMODE_BUMPTEX); + if (CheckLocalFlags(FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE)) + { + normalTS = UnpackNormalRGB(half4(normalMapSample.xy,1,1),_BumpScale); + metallic *= normalMapSample.z; + smoothness *= normalMapSample.w; + } + else + { + normalTS = UnpackNormalScale(half4(normalMapSample),_BumpScale); + } + + input.normalWSAndAnimBlend.xyz = normalize(TransformTangentToWorld(normalTS, tangentToWorld)); + #endif + + half2 cum_noise = 0; + // half2 cum_noise_xy = half2(0.5,0.5); + half3 screenDistort_Noise = half3(0,0,1);//xy:noise,z:mask; + half noiseMask = 1; + #if defined(_NOISEMAP) + #ifdef _DISTORT_REFRACTION + half3 refracVec = CustomRefract(-viewDirWS,input.normalWSAndAnimBlend.xyz,1/_RefractionIOR); + refracVec = TransformWorldToHClipDir(refracVec); + cum_noise = refracVec.xy; + // distortFlow = refracVec.xy * props._NormalRefractionBias; + #else + half4 noiseSample = SampleNoise(_NoiseOffset, _NoiseMap, noiseMap_uv, input.positionWS.xyz); + cum_noise = noiseSample.xy; + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON)) + { + cum_noise = cum_noise * 2 - 1; + } + noiseMask *= noiseSample.a; + _DistortionDirection.x += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + _DistortionDirection.y += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + #endif + UNITY_BRANCH + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_NOISE_MASKMAP)) + { + half4 noiseMaskSample = SampleTexture2DWithWrapFlags(_NoiseMaskMap,noiseMaskMap_uv,FLAG_BIT_WRAPMODE_NOISE_MASKMAP); + noiseMask *= GetColorChannel(noiseMaskSample,FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK); + } + _NoiseIntensity = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY,_NoiseIntensity,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + + cum_noise = cum_noise *_DistortionDirection.xy*_NoiseIntensity; + + #ifdef _PROGRAM_NOISE + cum_noise = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT,cum_noise,programNoise,_DistortPNoiseBlendOpacity); + #endif + + + + #if defined(_SCREEN_DISTORT_MODE) + screenDistort_Noise.xy = cum_noise; + screenDistort_Noise.z = noiseMask; + #endif + // #if defined(_SCREEN_DISTORT_MODE) + // cum_noise_xy = cum_noise * _ScreenDistortIntensity; + // #endif + + cum_noise *= noiseMask; + + #ifdef NB_DEBUG_DISTORT + return half4(cum_noise,0,1); + #endif + #endif + + // SampleAlbedo-------------------- + half4 albedo = 0; + + #if !defined(NB_DEPTH_SHADOW_PASS) + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_BACKCOLOR)) + { + _BaseColor = facing > 0 ? _BaseColor : _BaseBackColor; + } + #endif + + + Texture2D baseMap = _BaseMap; + + + + float2 mainTexNoise = cum_noise * _TexDistortion_intensity; + + MainTex_UV.xy += mainTexNoise;//主贴图纹理扭曲 + blendUv.xy += mainTexNoise; + + + UNITY_BRANCH + if (CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON) & !CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE)) + { + albedo = BlendTexture(_MainTex, MainTex_UV, blendUv) * _Color; + } + #if !defined(NB_DEPTH_SHADOW_PASS) + else if (CheckLocalFlags(FLAG_BIT_PARTICLE_CHORATICABERRAT)) + { + + _DistortionDirection.z = GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY,_DistortionDirection.z,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + _DistortionDirection.z *= 0.1; + albedo = DistortionChoraticaberrat(baseMap,originUV,MainTex_UV,_DistortionDirection.z,FLAG_BIT_WRAPMODE_BASEMAP); + } + #endif + else + { + albedo = BlendTexture(baseMap, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP); + } + + // #ifndef _CAMERA_OPAQUE_DISTORT_PASS + + albedo.a = GetColorChannel(albedo,FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA); + + albedo *= _BaseColor ; + #if !defined(NB_DEPTH_SHADOW_PASS) + albedo.rgb *= _BaseColorIntensityForTimeline; + #endif + // #endif + + + // #endif + + half alpha = albedo.a; + half3 result = albedo.rgb; + #if !defined(NB_DEPTH_SHADOW_PASS) + UNITY_BRANCH + if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX)) + { + ColorAdjustment(result,alpha,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + } + #endif + + #ifdef _FX_LIGHT_MODE_SIX_WAY + float4 rigRTBkSample = BlendTexture(_RigRTBk, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP); + float4 rigLBtFSample = BlendTexture(_RigLBtF, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP); + #endif + + + //光照模式 + #ifndef _FX_LIGHT_MODE_UNLIT + + InputData inputData; + InitializeInputData(input, tangentToWorld,viewDirWS, inputData); + metallic *= _MaterialInfo.x; + half3 specular = 0; + smoothness *= _MaterialInfo.y; + half occlusion = 1; + half3 pbrEmission = 0; + // return half4(inputData.bakedGI,1); + #if defined (_FX_LIGHT_MODE_BLINN_PHONG) || defined(_FX_LIGHT_MODE_HALF_LAMBERT) + half4 specularGloss = _SpecularColor; + #ifdef _FX_LIGHT_MODE_BLINN_PHONG + half4 blinnPhong = UniversalFragmentBlinnPhong(inputData,result.rgb, specularGloss, smoothness, pbrEmission, alpha,normalTS); + #else //_FX_LIGHT_MODE_HALF_LAMBERT + half4 blinnPhong = UniversalFragmentHalfLambert(inputData,result.rgb, specularGloss, smoothness, pbrEmission, alpha,normalTS); + #endif + result = blinnPhong.rgb; + alpha = blinnPhong.a; + #elif _FX_LIGHT_MODE_PBR + half4 pbr = UniversalFragmentPBR(inputData,result.rgb, metallic, specular, smoothness, occlusion, pbrEmission, alpha); + result = pbr.rgb; + alpha = pbr.a; + #elif _FX_LIGHT_MODE_SIX_WAY + BSDFData bsdfData = (BSDFData)0; + bsdfData.absorptionRange = GetAbsorptionRange(_SixWayInfo.x); + bsdfData.diffuseColor = albedo; + bsdfData.normalWS = inputData.normalWS; + bsdfData.tangentWS = input.tangentWS;//Check this + bsdfData.rigRTBk = rigRTBkSample.xyz * INV_PI;//AccordingTo SixWayForwardPass + bsdfData.rigLBtF = rigLBtFSample.xyz * INV_PI;//AccordingTo SixWayForwardPass + bsdfData.bakeDiffuseLighting0 = input.bakeDiffuseLighting0; + bsdfData.bakeDiffuseLighting1 = input.bakeDiffuseLighting1; + bsdfData.bakeDiffuseLighting2 = input.bakeDiffuseLighting2; + bsdfData.backBakeDiffuseLighting0 = input.backBakeDiffuseLighting0; + bsdfData.backBakeDiffuseLighting1 = input.backBakeDiffuseLighting1; + bsdfData.backBakeDiffuseLighting2 = input.backBakeDiffuseLighting2; + bsdfData.emissionInput = rigLBtFSample.a; + GetSixWayEmission(bsdfData,_SixWayEmissionRamp,_SixWayEmissionColor,CheckLocalFlags1(FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP));//Init Emission + bsdfData.alpha = rigRTBkSample.a * _BaseColor.a; + + ModifyBakedDiffuseLighting(bsdfData,inputData.bakedGI); + + half4 sixWay = UniversalFragmentSixWay(inputData,bsdfData); + + + // half3 dir = _MainLightPosition.xyz; + // dir = TransformToLocalFrame(dir, bsdfData); + // return half4(dir,1); + + result = sixWay.rgb; + alpha = sixWay.a; + + #endif + + #ifdef _ADDITIONAL_LIGHTS_VERTEX + result.rgb *= input.vertexLight; + #endif + + // input.normalWSAndAnimBlend.xyz = inputData.normalWS; + #endif + + + #ifdef _MATCAP + // URP + half3 normalVS = mul(input.normalWSAndAnimBlend.xyz, (float3x3)UNITY_MATRIX_I_V); // 逆转置矩阵 + //half3 positionVS = TransformWorldToView(input.positionWS); + + + float3 r = reflect(positionVS, normalVS); + r = normalize(r); + float m = 2.828427f * sqrt(r.z + 1.0); + float2 matCapUV = r.xy / m + 0.5; + half3 matCapSample = SAMPLE_TEXTURE2D(_MatCapTex,sampler_linear_clamp,matCapUV); + + matCapSample *= _MatCapColor.rgb; + + half3 matCapMutilResult = result * matCapSample; + half3 matAddResult = result + matCapSample; + half3 matCapResult = lerp(matAddResult,matCapMutilResult,_MatCapInfo.x); + + result = lerp(result,matCapResult,_MatCapColor.a); + #endif + + + + //流光部分 + half4 emission = half4(0, 0, 0,1); + #if defined(_EMISSION) + #ifdef _NOISEMAP + emission_uv += cum_noise * _Emi_Distortion_intensity; + #endif + // emission = tex2D_TryLinearizeWithoutAlphaFX(_EmissionMap,emission_uv); + emission = SampleTexture2DWithWrapFlags(_EmissionMap,emission_uv,FLAG_BIT_WRAPMODE_EMISSIONMAP); + emission.xyz *= emission.a; + _EmissionMapColor *= _EmissionMapColorIntensity; + emission.xyz *= _EmissionMapColor; + + #endif + + result += emission; + + + #if defined(_COLOR_RAMP) + half rampValue = 0; + if (CheckLocalFlags(FLAG_BIT_PARTICLE_RAMP_COLOR_MAP_MODE_ON)) + { + half4 RampColorSample = SampleTexture2DWithWrapFlags(_RampColorMap,colorRamp_uv,FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP); + rampValue = GetColorChannel(RampColorSample,FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP); + } + else + { + const int rampColorWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP); + if (rampColorWrapMode == 0 || rampColorWrapMode == 2) + { + rampValue = frac(colorRamp_uv.x); + } + else + { + rampValue = saturate(colorRamp_uv.x); + } + } + + half3 colorRampColorArr[] = {_RampColor0.rgb,_RampColor1.rgb,_RampColor2.rgb,_RampColor3.rgb,_RampColor4.rgb,_RampColor5.rgb}; + half colorRampColorTimeArr[] = {_RampColor0.a,_RampColor1.a,_RampColor2.a,_RampColor3.a,_RampColor4.a,_RampColor5.a}; + int colorRampColorCount = _RampColorCount & 0xFFFF; + + half colorRampAlphaArr[] = {_RampColorAlpha0.x,_RampColorAlpha0.z,_RampColorAlpha1.x,_RampColorAlpha1.z,_RampColorAlpha2.x,_RampColorAlpha2.z}; + half colorRampAlphaTimeArr[] = {_RampColorAlpha0.y,_RampColorAlpha0.w,_RampColorAlpha1.y,_RampColorAlpha1.w,_RampColorAlpha2.y,_RampColorAlpha2.w}; + int colorRampAlphaCount = _RampColorCount >> 16; + + half4 rampColor; + rampColor.rgb = GetGradientColorValue(colorRampColorArr,colorRampColorTimeArr,colorRampColorCount,rampValue); + rampColor.a = GetGradientAlphaValue(colorRampAlphaArr,colorRampAlphaTimeArr,colorRampAlphaCount,rampValue); + + rampColor *= _RampColorBlendColor; + + if (CheckLocalFlags(FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD)) + { + result += rampColor; + alpha += rampColor.a; + } + else + { + result *= rampColor; + alpha *= rampColor.a; + } + #endif + + + + //溶解部分 + #if defined(_DISSOLVE) + #ifdef _NOISEMAP + dissolve_uv += cum_noise * _DissolveOffsetRotateDistort.w; + + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_DISSOLVE_MASK)) + { + dissolve_mask_uv += cum_noise * _DissolveOffsetRotateDistort.w; + } + #endif + + half4 dissolveMapSample = SampleTexture2DWithWrapFlags(_DissolveMap,dissolve_uv,FLAG_BIT_WRAPMODE_DISSOLVE_MAP); + + half dissolveValue = GetColorChannel(dissolveMapSample,FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP); + + #ifdef _PROGRAM_NOISE + dissolveValue = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE,dissolveValue,programNoise,_DissolvePNoiseBlendOpacity); + #endif + + + dissolveValue = pow(dissolveValue,_Dissolve.y); + + + + + half dissolveMaskValue = 0; + half dissolveMaskStrength = 0; + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_DISSOLVE_MASK)) + { + half4 dissolveMaskSample = SampleTexture2DWithWrapFlags(_DissolveMaskMap,dissolve_mask_uv,FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP); + dissolveMaskValue = GetColorChannel(dissolveMaskSample,FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP); + dissolveMaskStrength = _Dissolve.z + GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + + if (_DissolveMaskMode < 0.5) + { + dissolveMaskValue = lerp(dissolveValue, dissolveMaskValue, dissolveMaskStrength); + dissolveValue = (dissolveValue +dissolveMaskValue)*0.5;//Smart Way By Panda + } + } + + #ifdef NB_DEBUG_DISSOLVE //后续Test类的关键字要找机会排除 + return half4(dissolveValue.rrr,1); + #endif + half dissolveStrenth = _Dissolve.x + GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + + half invSoftStep = 1/_Dissolve.w; + half dissolveValueBeforeSoftStep = dissolveValue - ((dissolveStrenth)*(invSoftStep + 1)-1)*_Dissolve.w ; + dissolveValue = dissolveValue*invSoftStep -(1+invSoftStep)*dissolveStrenth +1; + // dissolveValue = smoothstep(dissolveStrenth-_Dissolve.w,dissolveStrenth,dissolveValue);//Smart Way By Panda + + + dissolveValue = saturate(dissolveValue); + if(CheckLocalFlags(FLAG_BIT_PARTICLE_DISSOLVE_MASK)&&_DissolveMaskMode > 0.5) + { + dissolveMaskStrength = dissolveMaskStrength -1; + dissolveMaskValue = saturate(dissolveMaskValue - dissolveMaskStrength); + dissolveValue = lerp(1, dissolveValue, dissolveMaskValue); + } + + alpha *= dissolveValue; + #if !defined(NB_DEPTH_SHADOW_PASS) + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DISSOVLE_USE_RAMP)) + { + // half rampRange = (dissolveValueBeforeSoftStep - _Dissolve_Vec2.x)*_Dissolve_Vec2.y; + half rampRange = dissolveValueBeforeSoftStep; + rampRange = rampRange * _DissolveRampMap_ST.x +_DissolveRampMap_ST.z; + + half4 rampSample ; + if (CheckLocalFlags(FLAG_BIT_PARTICLE_DISSOLVE_RAMP_MAP)) + { + rampSample = SampleTexture2DWithWrapFlags(_DissolveRampMap,half2(rampRange,0.5),FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP); + } + else + { + half3 dissolveRampColorArr[] = {_DissolveRampColor0.rgb,_DissolveRampColor1.rgb,_DissolveRampColor2.rgb,_DissolveRampColor3.rgb,_DissolveRampColor4.rgb,_DissolveRampColor5.rgb}; + half dissolveRampColorTimeArr[] = {_DissolveRampColor0.a,_DissolveRampColor1.a,_DissolveRampColor2.a,_DissolveRampColor3.a,_DissolveRampColor4.a,_DissolveRampColor5.a}; + int dissolveRampColorCount = _DissolveRampCount & 0xFFFF; + + half dissolveRampAlphaArr[] = {_DissolveRampAlpha0.x,_DissolveRampAlpha0.z,_DissolveRampAlpha1.x,_DissolveRampAlpha1.z,_DissolveRampAlpha2.x,_DissolveRampAlpha2.z}; + half dissolveRampAlphaTimeArr[] = {_DissolveRampAlpha0.y,_DissolveRampAlpha0.w,_DissolveRampAlpha1.y,_DissolveRampAlpha1.w,_DissolveRampAlpha2.y,_DissolveRampAlpha2.w}; + int dissolveRampAlphaCount = _DissolveRampCount >> 16; + + const int rampWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP); + if (rampWrapMode == 0 || rampWrapMode == 2) + { + rampRange = frac(rampRange); + } + else + { + rampRange = saturate(rampRange); + } + + + rampSample.rgb = GetGradientColorValue(dissolveRampColorArr,dissolveRampColorTimeArr,dissolveRampColorCount,rampRange); + rampSample.a = GetGradientAlphaValue(dissolveRampAlphaArr,dissolveRampAlphaTimeArr,dissolveRampAlphaCount,rampRange); + } + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY)) + { + result = result * lerp(1,rampSample.rgb*_DissolveRampColor.rgb,rampSample.a*_DissolveRampColor.a); + } + else + { + result = lerp(result,rampSample.rgb*_DissolveRampColor.rgb,rampSample.a*_DissolveRampColor.a); + } + } + #endif + + + + #if !defined(NB_DEPTH_SHADOW_PASS) + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK)) + { + half lineMask = dissolveValueBeforeSoftStep;//SmoothStep要优化 + lineMask = saturate(NB_Remap01(lineMask,_Dissolve_Vec2.x-_Dissolve_Vec2.y,_Dissolve_Vec2 + _Dissolve_Vec2.y)); + lineMask = 1- lineMask; + + result = lerp(result,_DissolveLineColor.rgb,lineMask*_DissolveLineColor.a); + } + #endif + // + + + #endif + + //颜色渐变 + #ifdef _COLORMAPBLEND + #if defined(_NOISEMAP) + colorBlendMap_uv += cum_noise * _ColorBlendVec.x; //加入扭曲效果 + #endif + half4 colorBlend = SampleTexture2DWithWrapFlags(_ColorBlendMap,colorBlendMap_uv,FLAG_BIT_WRAPMODE_COLORBLENDMAP); + colorBlend.rgb = colorBlend.rgb * _ColorBlendColor.rgb; + colorBlend.a = lerp(1,colorBlend.a*_ColorBlendColor.a,_ColorBlendVec.z); + if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE)) + { + result *= colorBlend.rgb; + alpha *= colorBlend.a; + } + else + { + result.rgb = lerp(result.rgb,result.rgb * colorBlend.rgb,colorBlend.a); + } + #endif + + //遮罩部分 + #if defined(_MASKMAP_ON) + + #if defined(_NOISEMAP) + MaskMapuv += cum_noise * _MaskDistortion_intensity; //加入扭曲效果 + #endif + + half mask1 = 1; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT)) + { + const int maskMapWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP); + half maskMapTimeValue; + if (maskMapWrapMode == 0 || maskMapWrapMode == 2) + { + maskMapTimeValue = frac(MaskMapuv.x); + } + else + { + maskMapTimeValue = saturate(MaskMapuv.x); + } + + half maskMapAlphaArr[] = {_MaskMapGradientFloat0.x,_MaskMapGradientFloat0.z,_MaskMapGradientFloat1.x,_MaskMapGradientFloat1.z,_MaskMapGradientFloat2.x,_MaskMapGradientFloat2.z}; + half maskMapAlphaTimeArr[] = {_MaskMapGradientFloat0.y,_MaskMapGradientFloat0.w,_MaskMapGradientFloat1.y,_MaskMapGradientFloat1.w,_MaskMapGradientFloat2.y,_MaskMapGradientFloat2.w}; + int maskMapAlphaCount = _MaskMapGradientCount; + mask1 = GetGradientAlphaValue(maskMapAlphaArr,maskMapAlphaTimeArr,maskMapAlphaCount,maskMapTimeValue); + } + else + { + half4 maskmap1Sample = SampleTexture2DWithWrapFlags(_MaskMap, MaskMapuv,FLAG_BIT_WRAPMODE_MASKMAP); + mask1 = GetColorChannel(maskmap1Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1); + + } + + UNITY_BRANCH + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASK_MAP2)) + { + half mask2 = 1; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT)) + { + const int maskMap2WrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP2); + half maskMap2TimeValue; + if (maskMap2WrapMode == 0 || maskMap2WrapMode == 3) + { + maskMap2TimeValue = frac(MaskMapuv2.y); + } + else + { + maskMap2TimeValue = saturate(MaskMapuv2.y); + } + + half maskMap2AlphaArr[] = {_MaskMap2GradientFloat0.x,_MaskMap2GradientFloat0.z,_MaskMap2GradientFloat1.x,_MaskMap2GradientFloat1.z,_MaskMap2GradientFloat2.x,_MaskMap2GradientFloat2.z}; + half maskMap2AlphaTimeArr[] = {_MaskMap2GradientFloat0.y,_MaskMap2GradientFloat0.w,_MaskMap2GradientFloat1.y,_MaskMap2GradientFloat1.w,_MaskMap2GradientFloat2.y,_MaskMap2GradientFloat2.w}; + int maskMap2AlphaCount = _MaskMap2GradientCount; + mask2 = GetGradientAlphaValue(maskMap2AlphaArr,maskMap2AlphaTimeArr,maskMap2AlphaCount,maskMap2TimeValue); + } + else + { + half4 maskMap2Sample = SampleTexture2DWithWrapFlags(_MaskMap2, MaskMapuv2,FLAG_BIT_WRAPMODE_MASKMAP2); + mask2 = GetColorChannel(maskMap2Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2); + } + mask1 *= mask2; + } + + UNITY_BRANCH + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASK_MAP3)) + { + half mask3 = 1; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT)) + { + const int maskMap3WrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP3); + half maskMap3TimeValue; + if (maskMap3WrapMode == 0 || maskMap3WrapMode == 2) + { + maskMap3TimeValue = frac(MaskMapuv3.x); + } + else + { + maskMap3TimeValue = saturate(MaskMapuv3.x); + } + + half maskMap3AlphaArr[] = {_MaskMap3GradientFloat0.x,_MaskMap3GradientFloat0.z,_MaskMap3GradientFloat1.x,_MaskMap3GradientFloat1.z,_MaskMap3GradientFloat2.x,_MaskMap3GradientFloat2.z}; + half maskMap3AlphaTimeArr[] = {_MaskMap3GradientFloat0.y,_MaskMap3GradientFloat0.w,_MaskMap3GradientFloat1.y,_MaskMap3GradientFloat1.w,_MaskMap3GradientFloat2.y,_MaskMap3GradientFloat2.w}; + int maskMap3AlphaCount = _MaskMap3GradientCount; + mask3 = GetGradientAlphaValue(maskMap3AlphaArr,maskMap3AlphaTimeArr,maskMap3AlphaCount,maskMap3TimeValue); + } + else + { + half4 maskMap3Sample = SampleTexture2DWithWrapFlags(_MaskMap3, MaskMapuv3,FLAG_BIT_WRAPMODE_MASKMAP3); + mask3 = GetColorChannel(maskMap3Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3); + } + mask1 *= mask3; + } + + #ifdef _PROGRAM_NOISE + mask1 = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_MASK,mask1,programNoise,_MaskPNoiseBlendOpacity); + #endif + + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASK_REFINE)) + { + mask1 = pow(mask1,_MaskRefineVec.x); + mask1 = mask1 * _MaskRefineVec.y; + mask1 += _MaskRefineVec.z; + } + + mask1 = lerp(1,mask1,_MaskMapVec.x); + mask1 = saturate(mask1); + + #ifdef NB_DEBUG_MASK + return half4(mask1.rrr,1); + #endif + + + alpha *= mask1; //mask边缘 + #endif + + //菲涅 + + #if !defined(NB_DEPTH_SHADOW_PASS) + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_ON)) + { + half fresnelValue = 0; + if(!ignoreFresnel()) + { + half3 fresnelDir = normalize(viewDirWS+_FresnelRotation.rgb); + + half dotNV = dot(fresnelDir,input.normalWSAndAnimBlend.xyz) ; + fresnelValue = dotNV; + + + _FresnelUnit.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2);; + + // half fresnelHardness = - _FresnelUnit.w*0.5 +0.5; + fresnelValue = NB_Remap(fresnelValue,_FresnelUnit.x,_FresnelUnit.x + 1.01 - _FresnelUnit.w,0,1); + UNITY_BRANCH + if(!CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON)) + { + fresnelValue = 1- fresnelValue; + } + fresnelValue = pow(fresnelValue,_FresnelUnit.y); + + + // fresnelValue = smoothstep(0.5-fresnelHardness,0.5+fresnelHardness,fresnelValue); + } + + #ifdef NB_DEBUG_FRESNEL + return half4(fresnelValue.rrr*_FresnelUnit.z,1); + #endif + + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_FADE_ON)) + { + fresnelValue *= alpha; + alpha = lerp(alpha,fresnelValue,_FresnelUnit.z); + } + else + { + float fresnelColorIntensity = fresnelValue*_FresnelColor.a*_FresnelUnit.z; + + result = lerp(result,_FresnelColor.rgb,fresnelColorIntensity); + if (!CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA)) + { + alpha = max(alpha,fresnelColorIntensity);//颜色要不要不被主贴图Alpha影响呢? + } + + } + + } + + UNITY_BRANCH + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DEPTH_OUTLINE)) + { + half depthOutlineValue = 1- SoftParticles(_DepthOutline_Vec.x, _DepthOutline_Vec.y, sceneZ,thisZ); + depthOutlineValue *= _DepthOutline_Color.a; + half3 originResult = result; + //如何在一个pass里,完美的给出两个颜色的Fade。这个问题,没有想清楚。 + result = lerp(result,_DepthOutline_Color.rgb,clamp(depthOutlineValue*3,0,1)); + result = lerp(result,originResult,clamp(alpha-depthOutlineValue,0,1)); + alpha = max(alpha,depthOutlineValue); + + } + + + + + + + + //可以看https://www.cyanilux.com/tutorials/depth/ + // float4 projectedPosition = input.positionNDC; + // float thisZ1 = LinearEyeDepth(projectedPosition.z / projectedPosition.w, _ZBufferParams); + + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_DISTANCEFADE_ON)) + { + half fade = DepthFactor(thisZ, _Fade.x, _Fade.y); + alpha *= fade; + } + + + #if defined(_SOFTPARTICLES_ON) + + half softAlpha = SoftParticles(SOFT_PARTICLE_NEAR_FADE, SOFT_PARTICLE_INV_FADE_DISTANCE, sceneZ,thisZ); + alpha *= softAlpha; + + #endif + #endif + + + + + + + + //和粒子颜色信息运算。雨轩:乘顶点色。 + if(!CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR)) + { + #if !defined(NB_DEPTH_SHADOW_PASS) + result *= input.color.rgb; + #endif + alpha *= input.color.a; + } + // 程序额外的颜色 + #if !defined(NB_DEPTH_SHADOW_PASS) + result *= _ColorA.rgb; + #endif + alpha *= _ColorA.a; + // // alpha *= _ColorA * 0.8; + + + #if !defined(NB_DEPTH_SHADOW_PASS) + #ifdef _DEPTH_DECAL + alpha *= decalAlpha; + #endif + + half3 beforeFogResult = result; + result = MixFog(result,input.positionWS.w); + result = lerp(beforeFogResult, result, _fogintensity); + + UNITY_BRANCH + if (!CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX)) + { + ColorAdjustment(result,alpha,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + } + + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_LINEARTOGAMMA_ON)) + { + result.rgb = LinearToGammaSpace(result.rgb); + } + #endif + + + alpha *= _AlphaAll; + alpha = saturate(alpha); + + #if defined(NB_DEPTH_ONLY_PASS) + #ifdef _ALPHATEST_ON + clip(alpha - _Cutoff); + #endif + return half4(input.clipPos.z, 0, 0, 0); + #elif defined(NB_SHADOW_CASTER_PASS) + #ifdef _ALPHATEST_ON + clip(alpha - _Cutoff); + #endif + + if (_TransparentMode > 0.5f && _TransparentMode < 1.5f) + { + if (_TransparentShadowDitherToggle > 0.5f) + { + clip(NBShadowDitherMaskClip(input.clipPos, alpha)); + } + else + { + clip(alpha - 0.5); + } + } + + return 0; + #endif + + #if defined (_ALPHAPREMULTIPLY_ON) || defined(_ALPHAMODULATE_ON) + result *= alpha; + #ifdef _ALPHAPREMULTIPLY_ON + alpha *= _AdditiveToPreMultiplyAlphaLerp; + #endif + #endif + + + #ifdef _SCREEN_DISTORT_MODE + + //在这里可以进行Alpha的修改 + half screenDistortAlpha = alpha * screenDistort_Noise.z; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE)) + { + screenDistortAlpha = pow(screenDistortAlpha,_ScreenDistortAlphaPow); + screenDistortAlpha *= _ScreenDistortAlphaMulti; + screenDistortAlpha += _ScreenDistortAlphaAdd; + } + #ifdef _DEFERRED_DISTORT_PASS + result = half3(screenDistort_Noise.xy,1.0); + alpha = screenDistortAlpha * _ScreenDistortIntensity; + #endif + + #ifdef _CAMERA_OPAQUE_DISTORT_PASS + float2 screenDistortUV = screenUV; + screenDistortUV = screenDistortUV + screenDistort_Noise.xy * screenDistortAlpha * _ScreenDistortIntensity; + half4 screenTexDistortSample = SampleTexture2DWithWrapFlags(_CameraOpaqueTexture,screenDistortUV,FLAG_BIT_WRAPMODE_BASEMAP); + result = screenTexDistortSample.xyz; + alpha = 1; + // alpha = screenTexDistortSample.a; + #endif + + #endif + + + + + half4 color = half4(result, alpha); + + + + #ifdef _ALPHATEST_ON + clip(color.a - _Cutoff); + + #endif + + color = min(color,1000); + + + return color; + } + +#endif diff --git a/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitForwardPassNew.hlsl.meta b/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitForwardPassNew.hlsl.meta new file mode 100644 index 00000000..8e3f4d72 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitForwardPassNew.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9187c1d488f62d9458d6ce67858a43b3 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitInputNew.hlsl b/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitInputNew.hlsl new file mode 100644 index 00000000..a8e52cec --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitInputNew.hlsl @@ -0,0 +1,1623 @@ +#ifndef PARTICLESUNLITINPUT + #define PARTICLESUNLITINPUT + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "../HLSL/EffectFlags.hlsl" + + + //---------------particleInput------------------- + CBUFFER_START(UnityPerMaterial) + float4 _SoftParticleFadeParams; + float4 _CameraFadeParams; + // #ifdef _INTERSECT_ON + float _IntersectRadius; + half4 _IntersectColor; + // #endif + half _AdditiveToPreMultiplyAlphaLerp; + half _Saturability; + half _HueShift; + half _Contrast; + half3 _ContrastMidColor; + half4 _BaseMapColorRefine; + half _AlphaAll; + float4 _BaseMap_ST; + float4 _BaseMap_AnimationSheetBlend_ST;//20240826 暂时只是给AnimationSheetHelper用。 + half _AnimationSheetHelperBlendIntensity; + float4 _MaskMap_ST; + half4 _BaseColor; + half4 _BaseBackColor; + half _BaseColorIntensityForTimeline; + half4 _EmissionMap_ST; + half4 _NoiseMap_ST; + half4 _NoiseMaskMap_ST; + half4 _DistortionDirection; + half4 _BaseColorAddSubDiff; + half _fogintensity; + half _Emi_Distortion_intensity; + half _BaseMapUVRotation; + half _BaseMapUVRotationSpeed; + float _MaskMapUVRotation; + float _NoiseMapUVRotation; + half _ScreenDistortIntensity; + half _ScreenDistortAlphaPow; + half _ScreenDistortAlphaAdd; + half _ScreenDistortAlphaMulti; + half _NoiseIntensity; + half _RefractionIOR; + half _uvRapSoft; + half4 _EmissionMapColor; + half _EmissionMapColorIntensity; + + + //--------------光照部分------------- + float4 _BumpTex_ST; + half _BumpScale; + half4 _MaterialInfo; + half4 _SpecularColor; + //-----------SixWayLight---------- + half4 _SixWayInfo; + half4 _SixWayEmissionColor; + + half4 _MatCapColor; + half4 _MatCapInfo; + + half _EdgeFade; + half4 _NoiseOffset; + half4 _EmissionMapUVOffset; + half _EmissionMapUVRotation; + half _EmissionSelfAlphaWeight; + half _TexDistortion_intensity; + // //half _RJ_Distortion_intensity; + // half _XianXingCH_UVRota; + // half _jingxiangCH_dire; + + half _MaskDistortion_intensity; + half4 _BaseMapMaskMapOffset; + half4 _MaskMapOffsetAnition; + half4 _MaskMap3OffsetAnition; + half4 _MaskMapVec; + half4 _MaskRefineVec; + + int _MaskMapGradientCount; + half4 _MaskMapGradientFloat0; + half4 _MaskMapGradientFloat1; + half4 _MaskMapGradientFloat2; + int _MaskMap2GradientCount; + half4 _MaskMap2GradientFloat0; + half4 _MaskMap2GradientFloat1; + half4 _MaskMap2GradientFloat2; + int _MaskMap3GradientCount; + half4 _MaskMap3GradientFloat0; + half4 _MaskMap3GradientFloat1; + half4 _MaskMap3GradientFloat2; + + float4 _PCCenter; + float4 _TWParameter; + float _TWStrength; + float4 _Fade; + float _MaskMapRotationSpeed; + + + half _FrePower; + half _FresnelInOutSlider; + half4 _FresnelRotation; + half _FresnelSelfAlphaWeight; + half4 _FresnelUnit; + half4 _FresnelUnit2; + half4 _DepthOutline_Vec; + half4 _DepthOutline_Color; + half4 _FresnelColor; + half4 _ColorA; + float _TransparentMode; + float4 _ClipRect; + + float4 _CylinderMatrix0; + float4 _CylinderMatrix1; + float4 _CylinderMatrix2; + float4 _CylinderMatrix3; + + half4 _Color; + float4 _UI_MainTex_ST;//在UI中,RawImage组件的功能和正常的TexST不一致,所以这里使用另外传的方式。 + float4 _MainTex_Reverse_ST; + + half _Cutoff; + + float4 _MaskMap2_ST; + float4 _MaskMap3_ST; + + float time; + half _FresnelFadeDistance; + + half4 LB_RT; + + half4 _Dissolve; + half4 _DissolveMap_ST; + half4 _DissolveOffsetRotateDistort; + half4 _DissolveMaskMap_ST; + half _DissolveMaskMode; + + half4 _DissolveLineColor; + half4 _DissolveRampColor; + float4 _DissolveVoronoi_Vec; + half4 _DissolveVoronoi_Vec2; + float4 _DissolveVoronoi_Vec3; + float4 _DissolveVoronoi_Vec4; + half4 _DissolveRampMap_ST; + half4 _Dissolve_Vec2; + half _ProgramNoise_Rotate; + + half4 _SharedUV_ST; + half4 _SharedUV_Vec; + // half _SharedUV_Distort_Intensity; + + half4 _ColorBlendMap_ST; + float4 _ColorBlendMapOffset; + half4 _ColorBlendColor; + half4 _ColorBlendVec; + + half4 _RampColor0; + half4 _RampColor1; + half4 _RampColor2; + half4 _RampColor3; + half4 _RampColor4; + half4 _RampColor5; + half4 _RampColorAlpha0; + half4 _RampColorAlpha1; + half4 _RampColorAlpha2; + uint _RampColorCount; + half4 _RampColorBlendColor; + float4 _RampColorMapOffset; + half4 _RampColorMap_ST; + + half4 _DissolveRampColor0; + half4 _DissolveRampColor1; + half4 _DissolveRampColor2; + half4 _DissolveRampColor3; + half4 _DissolveRampColor4; + half4 _DissolveRampColor5; + half4 _DissolveRampAlpha0; + half4 _DissolveRampAlpha1; + half4 _DissolveRampAlpha2; + uint _DissolveRampCount; + + + half3 _VertexOffset_Vec; + half3 _VertexOffset_CustomDir; + half4 _VertexOffset_Map_ST; + + half4 _VertexOffset_MaskMap_ST; + half3 _VertexOffset_MaskMap_Vec; + + float _VAT_Toggle; + float _VATMode; + float _ImportScale; + float _TyFlowVATSubMode; + float _DeformingSkin; + float _SkinBoneCount; + float _RGBAEncoded; + float _RGBAHalf; + float _LinearToGamma; + float _VATIncludesNormals; + float _AffectsShadows; + float _TransparentShadowDitherToggle; + float _Frame; + float _Frames; + float _FrameInterpolation; + float _Loop; + float _InterpolateLoop; + float _Autoplay; + float _AutoplaySpeed; + + half _ParallaxMapping_Intensity; + half4 _ParallaxMapping_Map_ST; + half4 _ParallaxMapping_Vec; + half _WorldSpaceUVModeSelector; + half _ObjectSpaceUVModeSelector; + + uint _W9ParticleShaderFlags; + + uint _W9ParticleShaderFlags1; + + uint _W9ParticleShaderWrapFlags; + + uint _W9ParticleCustomDataFlag0; + uint _W9ParticleCustomDataFlag1; + uint _W9ParticleCustomDataFlag2; + uint _W9ParticleCustomDataFlag3; + + uint _UVModeFlag0; + uint _UVModeFlagType0; + + + uint _W9ParticleShaderColorChannelFlag; + uint _W9ParticleShaderPNoiseBlendFlag; + half _ProgramNoiseBaseBlendOpacity; + half _MaskPNoiseBlendOpacity; + half _DissolvePNoiseBlendOpacity; + half _DistortPNoiseBlendOpacity; + float4x4 _CustomLocalTransformLocalToWorld; + float4x4 _CustomLocalTransformWorldToLocal; + + CBUFFER_END + + #define NB_SHADER_FLAGS _W9ParticleShaderFlags + #define NB_SHADER_FLAGS1 _W9ParticleShaderFlags1 + #define NB_SHADER_WRAP_FLAGS _W9ParticleShaderWrapFlags + #define NB_SHADER_COLOR_CHANNEL_FLAG _W9ParticleShaderColorChannelFlag + #define NB_SHADER_PNOISE_BLEND_FLAG _W9ParticleShaderPNoiseBlendFlag + #define NB_CUSTOM_DATA_FLAG_0 _W9ParticleCustomDataFlag0 + #define NB_CUSTOM_DATA_FLAG_1 _W9ParticleCustomDataFlag1 + #define NB_CUSTOM_DATA_FLAG_2 _W9ParticleCustomDataFlag2 + #define NB_CUSTOM_DATA_FLAG_3 _W9ParticleCustomDataFlag3 + + float3x3 GetCustomLocalToWorld3x3() + { + return (float3x3)_CustomLocalTransformLocalToWorld; + } + + float3x3 GetCustomWorldToLocal3x3() + { + return (float3x3)_CustomLocalTransformWorldToLocal; + } + + float3 TransformWorldToObject_NB(float3 positionWS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return mul(_CustomLocalTransformWorldToLocal, float4(positionWS, 1.0)).xyz; + #else + return mul(unity_WorldToObject, float4(positionWS, 1.0)).xyz; + #endif + } + + float3 TransformObjectToWorld_NB(float3 positionOS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return mul(_CustomLocalTransformLocalToWorld, float4(positionOS, 1.0)).xyz; + #else + return mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz; + #endif + } + + float4 TransformObjectToHClip_NB(float3 positionOS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return TransformWorldToHClip(TransformObjectToWorld_NB(positionOS)); + #else + return TransformObjectToHClip(positionOS); + #endif + } + + float3 TransformWorldToObjectDir_NB(float3 dirWS, bool doNormalize = true) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + float3 dirOS = mul(GetCustomWorldToLocal3x3(), dirWS); + return doNormalize ? SafeNormalize(dirOS) : dirOS; + #else + float3 dirOS = mul((float3x3)unity_WorldToObject, dirWS); + return doNormalize ? SafeNormalize(dirOS) : dirOS; + #endif + } + + float3 TransformWorldToObjectNormal_NB(float3 normalWS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return SafeNormalize(mul(normalWS, GetCustomLocalToWorld3x3())); + #else + return SafeNormalize(mul(normalWS, (float3x3)unity_ObjectToWorld)); + #endif + } + + float3 TransformObjectToWorldDir_NB(float3 dirOS, bool doNormalize = true) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + float3 dirWS = mul(GetCustomLocalToWorld3x3(), dirOS); + return doNormalize ? SafeNormalize(dirWS) : dirWS; + #else + return TransformObjectToWorldDir(dirOS, doNormalize); + #endif + } + + float3 TransformObjectToWorldNormal_NB(float3 normalOS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return SafeNormalize(mul(normalOS, GetCustomWorldToLocal3x3())); + #else + return TransformObjectToWorldNormal(normalOS); + #endif + } + + float3 GetCustomLocalSpaceNormalizeViewDir(float3 positionOS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + float3 viewDir = TransformWorldToObject_NB(_WorldSpaceCameraPos) - positionOS; + return SafeNormalize(viewDir); + #else + return GetObjectSpaceNormalizeViewDir(positionOS); + #endif + } + + float GetCustomLocalOddNegativeScale() + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return determinant(GetCustomLocalToWorld3x3()) < 0.0 ? -1.0 : 1.0; + #else + return GetOddNegativeScale(); + #endif + } + + + bool CheckLocalFlags(uint bits) + { + return (_W9ParticleShaderFlags&bits) != 0; + } + bool CheckLocalFlags1(uint bits) + { + return (_W9ParticleShaderFlags1&bits) != 0; + } + int CheckLocalWrapFlags(uint bits) + { + bool bit0 = (_W9ParticleShaderWrapFlags&bits) != 0; + bool bit1 = (_W9ParticleShaderWrapFlags&(bits<<16)) != 0; + if(!bit0 && !bit1) + { + return 0; + } + else if(bit0 && !bit1) + { + return 1; + } + else if(!bit0 && bit1) + { + return 2; + } + else if(bit0 && bit1) + { + return 3; + } + else + { + return -1; + } + } + + + SamplerState sampler_linear_repeat; + SamplerState sampler_linear_clamp; + SamplerState sampler_linear_RepeatU_ClampV; + SamplerState sampler_linear_ClampU_RepeatV; + SamplerState sampler_point_clamp; + + + + half4 SampleTexture2D(Texture2D tex,float2 uv,SAMPLER( textureSampler),bool sampleLOD = false,int lod = 0) + { + if (sampleLOD) + { + return SAMPLE_TEXTURE2D_LOD(tex,textureSampler,uv,lod); + + } + else + { + return SAMPLE_TEXTURE2D(tex,textureSampler,uv); + } + } + + + half4 SampleTexture2DWithWrapFlags(Texture2D tex,float2 uv,uint bits,bool sampleLOD = false,int lod = 0) + { + #ifdef _CAMERA_OPAQUE_DISTORT_PASS + int wrapMode; + if (bits == FLAG_BIT_WRAPMODE_BASEMAP) + { + wrapMode = 1; + } + else + { + wrapMode = CheckLocalWrapFlags(bits); + } + + #else + const int wrapMode = CheckLocalWrapFlags(bits); + #endif + + + #if defined(SHADER_TARGET_GLSL) ||defined (SHADER_API_GLES)|| defined(SHADER_API_GLES3) + switch (wrapMode) + { + case 0: uv = frac(uv);break; + case 1: uv = saturate(uv);break; + case 2: uv = float2(saturate(uv.x),frac(uv.y));break; + case 3: uv = float2(frac(uv.x),saturate(uv.y));break; + } + if (sampleLOD) + { + return SAMPLE_TEXTURE2D_LOD(tex,sampler_linear_clamp,uv,lod);//SamplerWillIgnore;需要在GLSL相关平台打包时强制设置为Clamp循环。 + + } + else + { + return SAMPLE_TEXTURE2D(tex,sampler_linear_clamp,uv);//SamplerWillIgnore;需要在GLSL相关平台打包时强制设置为Clamp循环。 + } + + #else + + switch (wrapMode) + { + case 0: + return SampleTexture2D(tex,uv,sampler_linear_repeat,sampleLOD,lod); + break; + case 1: + return SampleTexture2D(tex,uv,sampler_linear_clamp,sampleLOD,lod); + case 2: + return SampleTexture2D(tex,uv,sampler_linear_RepeatU_ClampV,sampleLOD,lod); + break; + case 3: + return SampleTexture2D(tex,uv,sampler_linear_ClampU_RepeatV,sampleLOD,lod); + break; + default: + return SampleTexture2D(tex,uv,sampler_linear_repeat,sampleLOD,lod); + break; + } + #endif + } + + half GetColorChannel(half4 color, int bitPos) + { + uint bits = _W9ParticleShaderColorChannelFlag >> bitPos; + bits = bits & 3; + if (bits == 0) return color.x; + if (bits == 1) return color.y; + if (bits == 2) return color.z; + return color.w; + } + + samplerCUBE _FresnelHDRITex; + sampler2D _MainTex; + + + + #define SOFT_PARTICLE_NEAR_FADE _SoftParticleFadeParams.x //�궨��SOFT_PARTICLE_NEAR_FADE ��Ϊ_SoftParticleFadeParams���Ե�x����~ + #define SOFT_PARTICLE_INV_FADE_DISTANCE _SoftParticleFadeParams.y + + #define CAMERA_NEAR_FADE _CameraFadeParams.x + #define CAMERA_INV_FADE_DISTANCE _CameraFadeParams.y + + Texture2D _BaseMap; + Texture2D _NoiseMap; + Texture2D _NoiseMaskMap; + Texture2D _EmissionMap; + Texture2D _MaskMap; + Texture2D _MaskMap2; + Texture2D _MaskMap3; + #ifdef _NORMALMAP + Texture2D _BumpTex; + #endif + + #ifdef _FX_LIGHT_MODE_SIX_WAY + Texture2D _RigRTBk; + Texture2D _RigLBtF; + Texture2D _SixWayEmissionRamp; + #endif + + #ifdef _CAMERA_OPAQUE_DISTORT_PASS + Texture2D _CameraOpaqueTexture; + #endif + + #ifdef _MATCAP + Texture2D _MatCapTex; + #endif + + // Pre-multiplied alpha helper + #if defined(_ALPHAPREMULTIPLY_ON) //if( blend: One OneMinusSrcAlpha) + #define ALBEDO_MUL albedo + #else + #define ALBEDO_MUL albedo.a + #endif + + + #ifdef SOFT_UI_FRAME + sampler2D _SoftUIFrameMask; + // half4 LB_RT; + #endif + + #ifdef _DISSOLVE + Texture2D _DissolveMap; + Texture2D _DissolveMaskMap; + Texture2D _DissolveRampMap; + #endif + + # ifdef _COLORMAPBLEND + Texture2D _ColorBlendMap; + #endif + + #ifdef _COLOR_RAMP + Texture2D _RampColorMap; + #endif + + Texture2D _VATTex; + float4 _VATTex_TexelSize; + + + + half4 tex2D_TryLinearizeWithoutAlphaFX(sampler2D tex, float2 uv) + { + half4 outColor = 0; + + #if defined(PARTICLE)//UI下使用ParticleBase不需要做 Gamma2Linear 转换 + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON)) + { + outColor = tex2D(tex, uv); + } + else + { + outColor = TryLinearizeWithoutAlpha(tex2D(tex, uv)); + } + #endif + return outColor; + } + // + // Color blending fragment function + float4 MixParticleColor(float4 baseColor, float4 particleColor, float4 colorAddSubDiff) + { + #if defined(_COLOROVERLAY_ON) // Overlay blend + float4 output = baseColor; + output.rgb = lerp(1 - 2 * (1 - baseColor.rgb) * (1 - particleColor.rgb), 2 * baseColor.rgb * particleColor.rgb, step(baseColor.rgb, 0.5)); + output.a *= particleColor.a; + return output; + #elif defined(_COLORCOLOR_ON) // Color blend + half3 aHSL = RgbToHsv(baseColor.rgb); + half3 bHSL = RgbToHsv(particleColor.rgb); + half3 rHSL = half3(bHSL.x, bHSL.y, aHSL.z); + return half4(HsvToRgb(rHSL), baseColor.a * particleColor.a); + #elif defined(_COLORADDSUBDIFF_ON) // Additive, Subtractive and Difference blends based on 'colorAddSubDiff' + float4 output = baseColor; + output.rgb = baseColor.rgb + particleColor.rgb * colorAddSubDiff.x; + output.rgb = lerp(output.rgb, abs(output.rgb), colorAddSubDiff.y); + output.a *= particleColor.a; + return output; + #else // Default to Multiply blend + return baseColor * particleColor; + #endif + } + + // Soft particles - returns alpha value for fading particles based on the depth to the background pixel + float SoftParticles(float near, float far, float sceneZ,float thisZ) + { + float fade = 1; + if (near > 0.0 || far > 0.0) + { + // fade = saturate(far * ((sceneZ - near) - thisZ)); + float dist = sceneZ - thisZ; + fade = NB_Remap(dist, near,far,0,1); + } + return fade; + } + + + // Camera fade - returns alpha value for fading particles based on camera distance + half CameraFade(float near, float far, float thisZ) + { + return saturate((thisZ - near) * far); + } + + //相交位置渐变功能 + half4 Intersect(float IntersectRadius,half4 IntersectColor,float sceneZ,float thisZ) + { + half fade = sceneZ - thisZ; + fade =1- NB_Remap(fade,0,IntersectRadius,0,1); + + half4 c = 0; + c.rgb = IntersectColor.rgb; + c.a = fade*IntersectColor.a; + + return c; + } + + //遮挡穿透显示功能。 + half OccludeOpacity(half preAlpha,half _OccludeOpacity,half sceneZ,half thisZ) + { + half fakeZtest = step(thisZ,sceneZ); + return lerp(preAlpha*_OccludeOpacity,preAlpha,fakeZtest); + } + + + // Sample a texture and do blending for texture sheet animation if needed + half4 BlendTexture(sampler2D _Texture, float2 uv, float3 blendUv) + { + half4 color = tex2D_TryLinearizeWithoutAlphaFX(_Texture, uv); + + half4 color2; + #ifdef _FLIPBOOKBLENDING_ON + color2 = tex2D_TryLinearizeWithoutAlphaFX(_Texture, blendUv.xy); + color = lerp(color, color2, blendUv.z); + #endif + + // if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) + // { + // color2 = tex2D_TryLinearizeWithoutAlphaFX(_Texture, blendUv.xy); + // color = lerp(color, color2, blendUv.z); + // } + return color; + } + + half4 BlendTexture(Texture2D _Texture, float2 uv, float3 blendUv,uint bits) + { + half4 color = SampleTexture2DWithWrapFlags(_Texture,uv,bits); + half4 color2; + #ifdef _FLIPBOOKBLENDING_ON + color2 = SampleTexture2DWithWrapFlags(_Texture,blendUv.xy,bits); + color = lerp(color, color2, blendUv.z); + #endif + + // if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) + // { + // color2 = SampleTexture2DWithWrapFlags(_Texture, blendUv.xy,bits); + // color = lerp(color, color2, blendUv.z); + // } + return color; + } + + float2 UVOffsetAnimaiton(float2 UV,half2 OffsetSpeed) + { + float2 newUV = float2(OffsetSpeed.x*time+UV.x,OffsetSpeed.y*time+UV.y); + return newUV; + } + + // 采样噪波 + half4 SampleNoise(half4 NoiseOffset, Texture2D _Texture,float2 UV, half3 wordPos) + { + + float2 UV2 = float2(NoiseOffset.x * time + UV.x, NoiseOffset.y * time + UV.y); //_Time.y + + half4 color = SampleTexture2DWithWrapFlags(_Texture, UV2 ,FLAG_BIT_WRAPMODE_NOISEMAP); + // color.xy *= color.a; + + return color; + } + + + // // 替换颜色 + // half3 ReplaceColor_float(float3 In, float3 From, float3 To, float Range, float Fuzziness) + // { + // float Distance = distance(From, In); + // half3 Out = lerp(To, In, saturate((Distance - Range) / max(Fuzziness, 0.001))); //e-f? 0.00001 + // return Out; + // } + + //漩涡 圆形区域内变形。圆圈中心处的像素会旋转指定角度;圆圈中其他像素的旋转会随着相对于中心距离的变化而减小,在圆圈边缘处减小为零 + float2 UTwirl(float2 UV, float2 Center, float Strength) + { + float2 delta = UV - Center; + float angle = Strength * length(delta); + float x = cos(angle) * delta.x - sin(angle) * delta.y; + float y = sin(angle) * delta.x + cos(angle) * delta.y; + return float2(x + Center.x , y + Center.y ); + + } + + //Fresnel + half4 Unity_FresnelEffect(float3 Normal, float3 ViewDir, float Power, float Dire,half fresnelPos) + { + // half aa = saturate(dot(normalize(Normal), (ViewDir))); + half aa = dot(normalize(Normal), (ViewDir)); + aa = (aa+1)*0.5; + aa = NB_Remap(aa,fresnelPos,1,0,1); + aa = lerp(aa, (1 - aa), Dire); + half Out = pow( aa, Power); + return Out; + } + + half3 Rotation(half3 normalizedDirection,half3 rotation) + { + half4 Dir = half4(normalizedDirection,1); + float4x4 M_RotationX = float4x4( + + 1,0,0,0, + 0,cos(rotation.x),sin(rotation.x),0, + 0,-sin(rotation.x),cos(rotation.x),0, + 0,0,0,1 + + ); + float4x4 M_RotationY = float4x4( + + cos(rotation.y),0,sin(rotation.y),0, + 0,1,0,0, + -sin(rotation.y),0,cos(rotation.y),0, + 0,0,0,1 + + ); + float4x4 M_RotationZ = float4x4( + + cos(rotation.z),sin(rotation.z),0,0, + -sin(rotation.z),cos(rotation.z),0,0, + 0,0,1,0, + 0,0,0,1 + + ); + + return mul(M_RotationZ,mul(M_RotationY,mul(M_RotationX,Dir))); + + } + + //----------------公告板功能-----------------// + half3 BillBoard(float3 camPos, float3 vertexPos, int billboardType, int _ReverseZ) + { + float3 Z = normalize(mul(unity_WorldToObject, float4(_WorldSpaceCameraPos,1))); + if(_ReverseZ == 1) + { + Z *= -1; + } + Z.y *= billboardType; + + float3 Y = float3(0,1,0); + float3 X = normalize(cross(Z,Y)); + Y = normalize(cross(X,Z)); + float4x4 M = float4x4( + X.x, Y.x, Z.x, 0, + X.y, Y.y, Z.y, 0, + X.z, Y.z, Z.z, 0, + 0,0,0,1 + ); + float3 newPos = mul(M, vertexPos); + return newPos; + } + + half3 BillBoardNormal(float3 camPos, float3 vertexPos, int billboardType, int _ReverseZ) + { + float3 Z = normalize(mul(unity_WorldToObject, float4(_WorldSpaceCameraPos,1))); + if(_ReverseZ == 1) + { + Z *= -1; + } + Z.y *= billboardType; + + float3 Y = float3(0,1,0); + float3 X = normalize(cross(Y,Z)); + Y = normalize(cross(X,Z)); + float4x4 M = float4x4( + X.x, Y.x, Z.x, 0, + X.y, Y.y, Z.y, 0, + X.z, Y.z, Z.z, 0, + 0,0,0,1 + ); + float3 newPos = -mul(M, vertexPos); + return newPos; + } + + + float2 ParticleUVCommonProcess(float2 originUVAfterTwirlPolar,float4 scaleTilling,float2 offset = float2(0,0),float rotation = 0,float2 rotationCenter = float2(0.5,0.5)) + { + float2 uv = originUVAfterTwirlPolar; + uv = Rotate_Radians_float(uv,rotationCenter,rotation); + uv = uv*scaleTilling.xy + scaleTilling.zw; + + uv = UVOffsetAnimaiton(uv,offset); + + return uv; + } + + struct ParticleUVs + { + float2 mainTexUV; + float2 specUV; + float2 animBlendUV; + float2 maskMapUV; + float2 maskMap2UV; + float2 maskMap3UV; + float2 emissionUV; + float2 dissolve_uv; + float2 dissolve_mask_uv; + float2 dissolve_noise1_UV; + float2 dissolve_noise2_UV; + float2 colorBlendUV; + float2 noiseMapUV; + float2 noiseMaskMapUV; + float2 bumpTexUV; + float2 colorRampMapUV; + float2 sharedUV; + }; + + float2 getPosUVByPosUVMode(float3 pos,half posUVMode) + { + switch ((int)posUVMode) + { + case 0: + return pos.xy; + case 1: + return pos.xz; + case 2: + return pos.yz; + default: + return pos.xz; + } + } + + BaseUVs ProcessBaseUVs(float4 meshTexcoord0, float2 specialUVInTexcoord3,float4 VaryingsP_Custom1,float4 VaryingsP_Custom2,float3 postionOS,float3 positionWS,float2 screenUV) + { + //UV2的内容在外边就决定好。 + float2 defaultUVChannel = meshTexcoord0.xy; + float2 specialUVChannel = meshTexcoord0.zw; + #if _FLIPBOOKBLENDING_ON + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)) + { + specialUVChannel = specialUVInTexcoord3; + } + #else + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UV_FROM_MESH)) + { + //Mesh条件下开启使用特殊UV通道的情况 + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD1)) + { + specialUVChannel = VaryingsP_Custom1.xy; + } + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)) + { + specialUVChannel = VaryingsP_Custom2.xy; + } + } + else + { + //只有在粒子系统下开启特殊通道的情况,会在面板层引导合并相关内容。UI/Mesh不开启特殊通道没有意义。 + specialUVChannel = meshTexcoord0.zw; + } + #endif + + + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE)) + { + defaultUVChannel = defaultUVChannel*_MainTex_Reverse_ST.xy +_MainTex_Reverse_ST.zw; + } + //TODO:补写MeshUV的实现 + float2 cylinderUV = meshTexcoord0.xy; + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE)) + { + float4x4 _CylinderUVMatrix = float4x4(_CylinderMatrix0,_CylinderMatrix1,_CylinderMatrix2,_CylinderMatrix3); + postionOS = mul(_CylinderUVMatrix,float4(postionOS,1)); + cylinderUV = CylinderCoordinate(postionOS); + } + + float2 UVAfterTwirlPolar = defaultUVChannel; + if(CheckLocalFlags(FLAG_BIT_PARTICLE_UTWIRL_ON)) + { + UVAfterTwirlPolar = UTwirl(defaultUVChannel,_TWParameter.xy, _TWStrength); + } + if(CheckLocalFlags(FLAG_BIT_PARTICLE_POLARCOORDINATES_ON)) + { + float2 UVAfterTwirl = UVAfterTwirlPolar; + UVAfterTwirlPolar = PolarCoordinates(UVAfterTwirlPolar,_PCCenter.xy); + UVAfterTwirlPolar = lerp(UVAfterTwirl,UVAfterTwirlPolar,_PCCenter.z); + } + BaseUVs baseUVs = (BaseUVs)0; + baseUVs.defaultUVChannel = defaultUVChannel; + baseUVs.specialUVChannel = specialUVChannel; + baseUVs.uvAfterTwirlPolar = UVAfterTwirlPolar; + baseUVs.cylinderUV = cylinderUV; + + baseUVs.screenUV = screenUV; + baseUVs.worldPosUV = getPosUVByPosUVMode(positionWS,_WorldSpaceUVModeSelector); + baseUVs.objectPosUV = getPosUVByPosUVMode(postionOS,_ObjectSpaceUVModeSelector); + + baseUVs.sharedUV = defaultUVChannel; + float2 sharedUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_SHAREDUV,baseUVs); + _SharedUV_Vec.z += time * _SharedUV_Vec.w; + sharedUV = Rotate_Radians_float(sharedUV, half2(0.5, 0.5), _SharedUV_Vec.z); //主贴图旋转 + + sharedUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + sharedUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + sharedUV = sharedUV *_SharedUV_ST.xy +_SharedUV_ST.zw ; //主帖图UV重复和偏移 + + sharedUV = UVOffsetAnimaiton(sharedUV,_SharedUV_Vec.xy); + baseUVs.sharedUV = sharedUV; + + baseUVs.mainTexUV = defaultUVChannel; + float2 baseMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MAINTEX,baseUVs); + + float2 mainTexUV = 0; + _BaseMapUVRotation += time * _BaseMapUVRotationSpeed; + baseMapUV = Rotate_Radians_float(baseMapUV, half2(0.5, 0.5), _BaseMapUVRotation); //主贴图旋转 + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON) & !CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE)) + { + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE)) + { + float2 originUV = meshTexcoord0.xy;//精灵主贴图不调整。 + mainTexUV = originUV*_UI_MainTex_ST.xy+_UI_MainTex_ST.zw; + } + else + { + mainTexUV = baseMapUV*_UI_MainTex_ST.xy+_UI_MainTex_ST.zw; + } + } + else + { + baseMapUV.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + baseMapUV.y += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + mainTexUV = TRANSFORM_TEX(baseMapUV, _BaseMap); //主帖图UV重复和偏移 + } + mainTexUV = UVOffsetAnimaiton(mainTexUV,_BaseMapMaskMapOffset.xy); + baseUVs.mainTexUV = mainTexUV; + + return baseUVs; + } + + + void ParticleProcessUV(inout ParticleUVs particleUVs,float4 meshTexcoord0,float4 VaryingsP_Custom1,float4 VaryingsP_Custom2,BaseUVs baseUVs) + { + particleUVs.specUV = baseUVs.specialUVChannel; + + particleUVs.mainTexUV = baseUVs.mainTexUV; + //------------------------------------------------- + #ifdef _FLIPBOOKBLENDING_ON //开启序列帧融合 + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) + { + // float2 baseMapUV = (baseUVs.mainTexUV - _BaseMap_ST.zw)/_BaseMap_ST.xy; + //走AnimationSheetHelper脚本的情况,永远和baseMap同步。 + particleUVs.animBlendUV = meshTexcoord0.xy*_BaseMap_AnimationSheetBlend_ST.xy+_BaseMap_AnimationSheetBlend_ST.zw; + } + else + { + //走粒子的情况 + particleUVs.animBlendUV = meshTexcoord0.zw; + } + #endif + + + #if defined(_NORMALMAP) + float2 bumpTexUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_BUMPTEX,baseUVs); + bumpTexUV = TRANSFORM_TEX(bumpTexUV, _BumpTex); + particleUVs.bumpTexUV = bumpTexUV; + + #endif + + + + #if defined(_MASKMAP_ON) + + float2 MaskMapuv = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP,baseUVs); + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON)) + { + _MaskMapUVRotation += time * _MaskMapRotationSpeed; + } + + MaskMapuv= Rotate_Radians_float(MaskMapuv, half2(0.5, 0.5), _MaskMapUVRotation); + + MaskMapuv = TRANSFORM_TEX(MaskMapuv, _MaskMap); + + MaskMapuv.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + MaskMapuv.y += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + + MaskMapuv = UVOffsetAnimaiton(MaskMapuv,_MaskMapOffsetAnition.xy); + particleUVs.maskMapUV = MaskMapuv; + + UNITY_BRANCH + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASK_MAP2)) + { + float2 maskMap2UV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP_2,baseUVs); + maskMap2UV = Rotate_Radians_float(maskMap2UV,half2(0.5,0.5),_MaskMapVec.y); + maskMap2UV = maskMap2UV * _MaskMap2_ST.xy + _MaskMap2_ST.zw; + + maskMap2UV = UVOffsetAnimaiton(maskMap2UV,_MaskMapOffsetAnition.zw); + particleUVs.maskMap2UV = maskMap2UV; + } + + UNITY_BRANCH + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASK_MAP3)) + { + float2 maskMap3UV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP_3,baseUVs); + maskMap3UV = Rotate_Radians_float(maskMap3UV,half2(0.5,0.5),_MaskMapVec.z); + + maskMap3UV = maskMap3UV* _MaskMap3_ST.xy + _MaskMap3_ST.zw; + + maskMap3UV = UVOffsetAnimaiton(maskMap3UV,_MaskMap3OffsetAnition.xy); + particleUVs.maskMap3UV = maskMap3UV; + } + + #endif + + + #if defined(_EMISSION) + float2 emissionUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_EMISSION_MAP,baseUVs); + emissionUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + emissionUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + particleUVs.emissionUV = ParticleUVCommonProcess(emissionUV,_EmissionMap_ST,_EmissionMapUVOffset.xy,_EmissionMapUVRotation); + #endif + + #if defined(_DISSOLVE) + _DissolveMap_ST.z += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + _DissolveMap_ST.w += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + + float2 dissolveUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP,baseUVs); + particleUVs.dissolve_uv = ParticleUVCommonProcess(dissolveUV,_DissolveMap_ST,_DissolveOffsetRotateDistort.xy,_DissolveOffsetRotateDistort.z); + if(CheckLocalFlags(FLAG_BIT_PARTICLE_DISSOLVE_MASK)) + { + float2 dissolveMaskUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP,baseUVs); + particleUVs.dissolve_mask_uv = ParticleUVCommonProcess(dissolveMaskUV,_DissolveMaskMap_ST,float2(0,0),_DissolveOffsetRotateDistort.z); + } + #endif + + #ifdef _PROGRAM_NOISE + float2 programNoiseUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE,baseUVs); + programNoiseUV = Rotate_Radians_float(programNoiseUV,half2(0.5,0.5),_ProgramNoise_Rotate); + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE)) + { + _DissolveVoronoi_Vec4.x += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + _DissolveVoronoi_Vec4.y += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + particleUVs.dissolve_noise1_UV = programNoiseUV * _DissolveVoronoi_Vec.xy + _DissolveVoronoi_Vec4.xy + time*_DissolveVoronoi_Vec3.xy; + + } + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI)) + { + _DissolveVoronoi_Vec4.z += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + _DissolveVoronoi_Vec4.w += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + particleUVs.dissolve_noise2_UV = programNoiseUV * _DissolveVoronoi_Vec.zw + _DissolveVoronoi_Vec4.zw + time*_DissolveVoronoi_Vec3.zw; + } + #endif + + + #ifdef _COLORMAPBLEND + float2 colorBlendUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP,baseUVs); + colorBlendUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + colorBlendUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + particleUVs.colorBlendUV = ParticleUVCommonProcess(colorBlendUV,_ColorBlendMap_ST,_ColorBlendMapOffset.xy,_ColorBlendVec.w); + + #endif + #ifdef _COLOR_RAMP + float2 colorRampMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP,baseUVs); + particleUVs.colorRampMapUV = ParticleUVCommonProcess(colorRampMapUV,_RampColorMap_ST,_RampColorMapOffset.xy,_RampColorMapOffset.w); + #endif + half cum_noise = 0; + + //TODO + + #if defined(_NOISEMAP) + + //和ParticleUVCommonProcess相比,此处没有UV动画,NoiseMap的UV流动在最终的SampleNoise中进行 + float2 noiseMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_NOISE_MAP,baseUVs); + particleUVs.noiseMapUV = ParticleUVCommonProcess(noiseMapUV,_NoiseMap_ST,half2(0,0),_NoiseMapUVRotation); + + UNITY_BRANCH + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_NOISE_MASKMAP)) + { + float2 noiseMaskMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP,baseUVs); + particleUVs.noiseMaskMapUV = ParticleUVCommonProcess(noiseMaskMapUV,_NoiseMaskMap_ST,half2(0,0),0); + + } + #endif + + + + } + + Texture2D _VertexOffset_Map; + Texture2D _VertexOffset_MaskMap; + + // half3 _VertexOffset_Vec; + // half3 _VertexOffset_CustomDir; + // half4 _VertexOffset_Map_ST; + + half3 VetexOffset(half3 positionOS,half2 originUV,half2 originMaskUV,half3 normalOS,out half3 offsetOS) + { + half2 uv = TRANSFORM_TEX(originUV,_VertexOffset_Map); + uv = UVOffsetAnimaiton(uv,_VertexOffset_Vec.xy); + // half vertexOffsetSample = tex2Dlod(_VertexOffset_Map,half4(uv,0,0)); + half vertexOffsetSample = SampleTexture2DWithWrapFlags(_VertexOffset_Map,uv,FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP,true,0); + // UNITY_BRANCH + // if(CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP)) + // { + // vertexOffsetSample = SAMPLE_TEXTURE2D_LOD(_VertexOffset_Map,sampler_linear_clamp,uv,0); + // } + // else + // { + // vertexOffsetSample = SAMPLE_TEXTURE2D_LOD(_VertexOffset_Map,sampler_linear_repeat,uv,0); + // } + + if (!CheckLocalFlags1(FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO)) + { + vertexOffsetSample = vertexOffsetSample*2-1; + } + + half vertexOffsetMask = 1; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_VERTEXOFFSET_MASKMAP)) + { + half2 maskUV = TRANSFORM_TEX(originMaskUV,_VertexOffset_MaskMap); + maskUV = UVOffsetAnimaiton(maskUV,_VertexOffset_MaskMap_Vec.xy); + half vertexOffsetMaskSample = SampleTexture2DWithWrapFlags(_VertexOffset_MaskMap,maskUV,FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP,true,0); + vertexOffsetMask = lerp(1,vertexOffsetMaskSample,_VertexOffset_MaskMap_Vec.z); + } + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR)) + { + offsetOS = normalOS*_VertexOffset_Vec.z*vertexOffsetSample*vertexOffsetMask; + } + else + { + offsetOS = _VertexOffset_CustomDir*_VertexOffset_Vec.z*vertexOffsetSample*vertexOffsetMask; + } + + return positionOS + offsetOS; + + } + + //向UV横向两边的色散。 + half4 DistortionChoraticaberrat(Texture2D baseTexture,half2 originUV, half2 uvAfterNoise,half ChoraticaberratIntensity,uint bits) + { + half2 delta = half2(originUV.x *2-1,0); + + if(CheckLocalFlags(FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE)) + { + half2 NoiseIntensity = uvAfterNoise - originUV; + // half noiseXIntensity = abs(NoiseIntensity.x); + // delta *= ChoraticaberratIntensity*noiseXIntensity; + delta = NoiseIntensity*ChoraticaberratIntensity*10; + } + else + { + delta *= ChoraticaberratIntensity; + } + + half2 ra = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise,bits).xw; + ra.r *= ra.y; + half2 ga = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise - delta,bits).yw; + ga.r *= ga.y; + half2 ba = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise - delta*2,bits).zw; + ba.r *= ba.y; + return half4(ra.r,ga.r,ba.r,clamp(ra.y*0.5+ga.y*0.5+ba.y*0.5,0,1)); + } + + bool needSceneDepth() + { + #if defined(_DEPTH_DECAL) || defined(_SOFTPARTICLES_ON) + return true; + #endif + + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DEPTH_OUTLINE)) + { + return true; + } + + return false; + } + + bool needEyeDepth() + { + #if defined(_SOFTPARTICLES_ON) + return true; + #endif + + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DEPTH_OUTLINE)||CheckLocalFlags(FLAG_BIT_PARTICLE_DISTANCEFADE_ON)) + { + return true; + } + + return false; + } + + bool needPositionVS() + { + #if defined(_MATCAP) + return true; + #endif + + if (unity_OrthoParams.w == 1) + { + return true; + } + return false; + } + + bool ignoreFresnel() + { + #if defined(PARTICLE_BACKFACE_PASS) + return true; + #endif + return false; + } + + float3 CustomRefract(float3 incident, float3 normal, float eta) + { + float N_dot_I = dot(normal, incident); + float k = 1.0f - eta * eta * (1.0f - N_dot_I * N_dot_I); + + // 检查全内反射 + if (k < 0.0) + { + // 全内反射时返回零向量 + return float3(0, 0, 0); + } + else + { + // 计算折射方向 + return eta * incident - (eta * N_dot_I + sqrt(k)) * normal; + } + } + + Texture2D _ParallaxMapping_Map; + + half2 ParallaxMappingSimple(half2 texCoords, half3 viewDir) + { + float height = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,texCoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; + height *= _ParallaxMapping_Intensity; + viewDir = normalize(viewDir); + viewDir.xy /= (viewDir.z); + texCoords -= viewDir.xy * height; + return texCoords; + } + + half2 ParallaxMappingPeelDepth(half2 texCoords, half3 viewDir) + { + const float minLayers = 2; + const float maxLayers = 32; + float numLayers = lerp(maxLayers, minLayers, abs(dot(half3(0.0, 0.0, 1.0), viewDir)));//视线越垂直于表面,层数越少,反之越多。 + float layerDepth = 1/numLayers; + float currentLayerDepth = 0; + // viewDir.xy/=viewDir.z; + half2 p = viewDir.xy*_ParallaxMapping_Intensity; + half2 deltaTexcoord = p/numLayers; + + half2 currentTexcoords = texCoords; + float currentMapDepthValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,currentTexcoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; + + [loop] + while (currentLayerDepth < currentMapDepthValue ) + { + currentTexcoords -= deltaTexcoord; + currentMapDepthValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,currentTexcoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; + currentLayerDepth += layerDepth; + } + + return currentTexcoords; + + } + float2 ParallaxOcclusionMapping(float2 texCoords, float3 viewDir) + { + texCoords = texCoords * _ParallaxMapping_Map_ST + _ParallaxMapping_Map_ST.zw; + // number of depth layers + // const float minLayers = 10; + // const float maxLayers = 10; + const float minLayers = _ParallaxMapping_Vec.x; + const float maxLayers = _ParallaxMapping_Vec.y; + float numLayers = lerp(maxLayers, minLayers, abs(dot(half3(0.0, 0.0, 1.0), viewDir))); + // calculate the size of each layer + float layerDepth = 1.0 / numLayers; + // depth of current layer + float currentLayerDepth = 0.0; + // the amount to shift the texture coordinates per layer (from vector P) + float2 P = viewDir.xy / viewDir.z * _ParallaxMapping_Intensity; + float2 deltaTexCoords = P / numLayers; + + // get initial values + float2 currentTexCoords = texCoords; + float currentDepthMapValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map, currentTexCoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; + currentLayerDepth = clamp(currentLayerDepth,0,1); + + int i = 0; + [loop] + while(currentLayerDepth < currentDepthMapValue && i= timeArr[arrCount - 1]) { + // return int2(arrCount - 1, arrCount); // 大于等于最大值 + // } + + // 顺序查找第一个大于X的元素索引 + [unroll] + for (int i = 0; i < arrCount; i++) { + if (timeArr[i] > gradientTime) { + return int2(i - 1, i); // 返回区间索引 + } + } + return int2(-1, 0); // 理论上不会执行此处 + } + half GetGradientIndexInterval(half timeArr[6],int arrCount,int2 indexes,half gradientTime) + { + //超出范围的直接在外面就判断好。 + // half smallVal = indexes.x < 0 ? 0:timeArr[indexes.x]; + half smallVal = timeArr[indexes.x]; + // half bigVal = indexes.y >= arrCount ? 1 : timeArr[indexes.y]; + half bigVal = timeArr[indexes.y]; + return (gradientTime - smallVal) / (bigVal - smallVal); + } + + half3 GetGradientColorValue(half3 colorArr[6],half timeArr[6], int arrCount,half gradientTime) + { + if (gradientTime <= timeArr[0]) + { + return colorArr[0]; + } + else if (gradientTime >= timeArr[arrCount - 1] ) + { + return colorArr[arrCount - 1]; + } + else + { + int2 indexes = GetGradientIndex(timeArr, arrCount, gradientTime); + half interval = GetGradientIndexInterval(timeArr, arrCount, indexes, gradientTime); + interval = SmoothStep01(interval); + return lerp(colorArr[indexes.x], colorArr[indexes.y], interval); + } + } + + half GetGradientAlphaValue(half alphaArr[6],half timeArr[6], int arrCount,half gradientTime) + { + if (gradientTime <= timeArr[0]) + { + return alphaArr[0]; + } + else if (gradientTime >= timeArr[arrCount - 1] ) + { + return alphaArr[arrCount - 1]; + } + else + { + int2 indexes = GetGradientIndex(timeArr, arrCount, gradientTime); + half interval = GetGradientIndexInterval(timeArr, arrCount, indexes, gradientTime); + interval = SmoothStep01(interval);//TODO:消耗很大,如何避免? + half alpha = lerp(alphaArr[indexes.x], alphaArr[indexes.y], interval); + alpha *= alpha;//Make Alpha Smoother + return alpha ; + } + } + + void ColorAdjustment(inout half3 result,inout half alpha,half4 customData1,half4 customData2) + { + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_HUESHIFT_ON)) + { + half3 hsv = RgbToHsv(result); + _HueShift = GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT,_HueShift,customData1,customData2); + hsv.r += _HueShift; + result = HsvToRgb(hsv); + } + + UNITY_BRANCH + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST)) + { + _Contrast = GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST,_Contrast,customData1,customData2); + result.rgb = lerp(_ContrastMidColor,result.rgb,_Contrast); + } + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_SATURABILITY_ON)) + { + half3 resultWB = luminance(result); + _Saturability = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_SATURATE,_Saturability,customData1,customData2); + result.rgb = lerp(resultWB.rgb, result.rgb, _Saturability); + } + + + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE)) + { + half3 colorA = result.rgb*_BaseMapColorRefine.x; + half3 colorB = pow(result.rgb,_BaseMapColorRefine.y)*_BaseMapColorRefine.z; + result.rgb = lerp(colorA,colorB,_BaseMapColorRefine.w); + } + + if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA)) + { + result.rgb *= alpha; + } + + + } + +#endif diff --git a/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitInputNew.hlsl.meta b/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitInputNew.hlsl.meta new file mode 100644 index 00000000..925dcdff --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/HLSL/ParticlesUnlitInputNew.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 03da5256bb8bf0b4496b10ee6b449be4 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders/Shader/ParticleBase.shader b/Packages/NB_FX/NBShaders/Shader/ParticleBase.shader new file mode 100644 index 00000000..8441ba65 --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/ParticleBase.shader @@ -0,0 +1,1184 @@ +Shader "Effects/NBShader(Legacy)" +{ + Properties + { + _MeshSourceMode("Mesh来源模式",Float) = 0 + _UIEffect_Toggle("UI模式_Toggle",Float) = 0 + _DistortionBothDirection_Toggle("__DistortionBothDirection_Toggle",Float) = 0 + _DistanceFade_Toggle("_DistanceFade_Toggle",Float) = 0 + _ChangeSaturability_Toggle("__ChangeSaturability_Toggle",Float) = 0 + _Mask_Toggle("__Mask_Toggle",Float) = 0 + _Mask_RotationToggle("__Mask_RotationToggle",Float) = 0 + _Mask2_Toggle("__Mask2_Toggle",Float) = 0 + _Mask3_Toggle("__Mask3_Toggle",Float) = 0 + _BaseBackColor_Toggle("__BaseBackColor_Toggle",Float) = 0 + _UseUV1_Toggle("__UseUV1_Toggle",Float) = 0 + _TransparentMode("_TransparentMode",Float) = 1 + _ForceZWriteToggle("_ForceZWriteToggle",Float) = 0 + _VAT_Toggle("VAT顶点动画图",Float) = 0 + _VATMode("VAT模式",Float) = 0 + [NoScaleOffset]_VATTex("VAT texture", 2D) = "black" {} + _ImportScale("ImportScale", Float) = 0.01 + [HideInInspector] _TyFlowVATSubMode("TyFlow VAT Sub Mode", Float) = 0 + _DeformingSkin("Deforming skin", Float) = 0 + _SkinBoneCount("Skin bone count", Float) = 2 + _RGBAEncoded("RGBA encoded", Float) = 1 + _RGBAHalf("RGBA half", Float) = 1 + _LinearToGamma("Gamma correction", Float) = 1 + _VATIncludesNormals("VAT includes normals", Float) = 0 + [HideInInspector] _HoudiniVATSubMode("Houdini VAT Sub Mode", Float) = 0 + [HideInInspector] _B_autoPlayback("Auto Playback", Float) = 1 + [HideInInspector] _gameTimeAtFirstFrame("Game Time at First Frame", Float) = 0 + [HideInInspector] _playbackSpeed("Playback Speed", Float) = 1 + [HideInInspector] _houdiniFPS("Houdini FPS", Float) = 24 + [HideInInspector] _displayFrame("Display Frame", Float) = 0 + [HideInInspector] _B_interpolate("Interframe Interpolation", Float) = 1 + [HideInInspector] _animateFirstFrame("Animate First Frame", Float) = 0 + [HideInInspector] _frameCount("Frame Count", Float) = 1 + [HideInInspector] _boundMinX("Bound Min X", Float) = -1 + [HideInInspector] _boundMinY("Bound Min Y", Float) = -1 + [HideInInspector] _boundMinZ("Bound Min Z", Float) = -1 + [HideInInspector] _boundMaxX("Bound Max X", Float) = 1 + [HideInInspector] _boundMaxY("Bound Max Y", Float) = 1 + [HideInInspector] _boundMaxZ("Bound Max Z", Float) = 1 + [HideInInspector] _globalPscaleMul("Global Piece Scale Multiplier", Float) = 1 + [HideInInspector] _B_pscaleAreInPosA("Piece Scales in Position Alpha", Float) = 1 + [HideInInspector] _widthBaseScale("Width Base Scale", Float) = 0.2 + [HideInInspector] _heightBaseScale("Height Base Scale", Float) = 0.2 + [HideInInspector] _B_hideOverlappingOrigin("Hide Overlapping Origin", Float) = 1 + [HideInInspector] _originRadius("Origin Effective Radius", Float) = 0.02 + [HideInInspector] _B_CAN_SPIN("Particles Can Spin", Float) = 0 + [HideInInspector] _B_spinFromHeading("Compute Spin from Heading", Float) = 0 + [HideInInspector] _spinPhase("Particle Spin Phase", Float) = 0 + [HideInInspector] _scaleByVelAmount("Scale by Velocity Amount", Float) = 1 + [HideInInspector] _particleTexUScale("Particle Texture U Scale", Float) = 1 + [HideInInspector] _particleTexVScale("Particle Texture V Scale", Float) = 1 + [HideInInspector] _B_LOAD_POS_TWO_TEX("Positions Require Two Textures", Float) = 0 + [HideInInspector] _B_UNLOAD_ROT_TEX("Use Compressed Normals", Float) = 0 + [HideInInspector] _B_LOAD_COL_TEX("Load Color Texture", Float) = 0 + [HideInInspector] _B_LOAD_LOOKUP_TABLE("Load Lookup Table", Float) = 0 + [HideInInspector][NoScaleOffset] _posTexture("Houdini Position Texture", 2D) = "black" {} + [HideInInspector][NoScaleOffset] _posTexture2("Houdini Position Texture 2", 2D) = "black" {} + [HideInInspector][NoScaleOffset] _rotTexture("Houdini Rotation Texture", 2D) = "black" {} + [HideInInspector][NoScaleOffset] _colTexture("Houdini Color Texture", 2D) = "white" {} + [HideInInspector][NoScaleOffset] _lookupTable("Houdini Lookup Table", 2D) = "white" {} + _AffectsShadows("Affects shadows", Float) = 0 + _TransparentShadowDitherToggle("半透明Dither阴影", Float) = 0 + _Frame("Frame", Float) = 0 + _Frames("Frames", Float) = 10 + _FrameInterpolation("Frame interpolation", Float) = 1 + _Loop("Loop", Float) = 1 + _InterpolateLoop("Interpolate loop", Float) = 1 + _Autoplay("Autoplay", Float) = 0 + _AutoplaySpeed("AutoplaySpeed", Float) = 1 + + _Dissolve_Toggle("__Dissolve_Toggle",Float) = 0 + _DissolveMask_Toggle("__DissolveMask_Toggle",Float) = 0 + _Dissolve_useRampMap_Toggle("__Dissolve_useRampMap_Toggle",Float) = 0 + + _ProgramNoise_Toggle("_ProgramNoise_Toggle",Float) = 0 + _ProgramNoise_Simple_Toggle("_ProgramNoise_Simple_Toggle",Float) = 0 + _ProgramNoise_Rotate("_ProgramNoise_Rotate",Float) = 0 + _ProgramNoise_Voronoi_Toggle("_ProgramNoise_Voronoi_Toggle",Float) = 0 + _ProgramNoiseBaseBlendOpacity("两种程序噪波混合强度",Float) = 0 + + _ColorMultiAlpha("颜色乘以透明度",Float) = 0 + + _FresnelMode("__FresnelMode",Float) = 0 + _InvertFresnel_Toggle("__InvertFresnel_Toggle",Float) = 0 + _HueShift_Toggle("__HueShift_Toggle",Float) = 0 + _ColorAdjustmentOnlyAffectMainTex("颜色调整仅影响主贴图开关",Float) = 0 + _BackFaceColor_Toggle("_BackFaceColor_Toggle",Float) = 0 + _BackFirstPassToggle("_BackFirstPassToggle",Float) = 0 + + _PolarCordinateOnlySpecialFunciton_Toggle("极坐标仅对特殊功能生效_Toggle",Float) = 0 + + _CustomData1X_MainTexOffsetX_Toggle("_CustomData1X_MainTexOffsetX_Toggle",Float) = 0 + _CustomData1Y_MainTexOffsetY_Toggle("_CustomData1Y_MainTexOffsetY_Toggle",Float) = 0 + _CustomData1Z_Dissolve_Toggle("_CustomData1Z_Dissolve_Toggle",Float) = 0 + _CustomData1W_HueShift_Toggle("_CustomData1W_HueShift_Toggle",Float) = 0 + _CustomData2X_MaskMapOffsetX_Toggle("_CustomData2X_MaskMapOffsetX_Toggle",Float) = 0 + _CustomData2Y_MaskMapOffsetY_Toggle("_CustomData2Y_MaskMapOffsetY_Toggle",Float) = 0 + _CustomData2Z_FresnelOffset_Toggle("_CustomData2Z_FresnelOffset_Toggle",Float) = 0 + _CustomData2W_Toggle("_CustomData2W_Toggle",Float) = 0 + +// [PerRendererData] [MainTexture] _MainTex("Sprite Texture-ignore", 2D) = "white" {} + [PerRendererData] _MainTex ("Sprite Texture-ignore", 2D) = "white" {} + _Color("颜色贴图叠加", Color) = (1,1,1,1) + _UI_MainTex_ST("UI模式主贴图 xy:UV缩放 zw:UV偏移",vector) = (1,1,0,0) + _MainTex_Reverse_ST("MainTex_Reverse_ST-ignore",Vector) = (1,1,0,0) + + _BaseMap ("主贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _BaseMapMaskMapOffset ("xy主贴图偏移速度", vector) = (0, 0, 0, 0) + + _BaseMapUVRotation ("主贴图旋转", Range(0, 360)) = 0 + _BaseMapUVRotationSpeed ("主贴图旋转速度",Float) = 0 + [HDR]_BaseColor ("主贴图颜色_hdr", Color) = (1, 1, 1, 1)//HDR颜色不需要做Gamma Linear转换,Unity默认用Linear颜色 +// _BaseColor ("Base Color", Color) = (1, 1, 1, 1)//HDR颜色不需要做Gamma Linear转换,Unity默认用Linear颜色 + [HDR]_BaseBackColor ("背面颜色_hdr", Color) = (1, 1, 1, 1)//HDR颜色不需要做Gamma Linear转换,Unity默认用Linear颜色 + _BaseColorIntensityForTimeline("整体颜色强度", Range(0,10)) = 1 //独立出来是以为Timeline K颜色的时候会很奇怪的影响色相 + _Saturability("饱和度", range(0,1)) = 0 + _Contrast_Toggle("__Contrast_Toggle",Float) = 0 + _Contrast("对比度", Float) = 1 + _ContrastMidColor ("对比度中值颜色", Color) = (0.5, 0.5, 0.5, 1)//HDR颜色不需要做Gamma Linear转换,Unity默认用Linear颜色 + _HueShift("色相",Range(0,1)) = 0 + _BaseMapColorRefine_Toggle ("__BaseMapColorRefine_Toggle",Float) = 0 + _BaseMapColorRefine("主贴图颜色Refine",Vector) = (1,1,2,1) + _AlphaAll("整体透明度",Range(0,1)) = 1 + _IgnoreVetexColor_Toggle("_IgnoreVetexColor_Toggle",Float) = 0 + _MainTexPNoiseBlendOpacity("主贴图噪波图混合强度",Float) = 1 + + + _SpecialUVChannelMode("特殊UV通道选择",Float) = 0 + + _CylinderUVRotate("圆柱UV旋转",Vector) = (0,0,90,0) + _CylinderUVPosOffset("圆柱UV位置偏移",Vector) = (0,0,0,0) + _CylinderMatrix0("圆柱偏移矩阵0",Vector) = (0,0,0,0) + _CylinderMatrix1("圆柱偏移矩阵1",Vector) = (0,0,0,0) + _CylinderMatrix2("圆柱偏移矩阵2",Vector) = (0,0,0,0) + _CylinderMatrix3("圆柱偏移矩阵3",Vector) = (0,0,0,0) + + _Cutoff ("裁剪位置", float) = 0 + + //--------------光照部分------------- + _FxLightMode("灯光模式",Float) = 0 + _BumpMapToggle("法线贴图开关",Float) = 0 + _BumpMapMaskMode("法线贴图多通道模式",Float) = 0 + _BumpScale("Scale", Float) = 1.0 + _BumpTex("Normal Map", 2D) = "bump" {} + _MaterialInfo("x:金属度,y:光滑度",Vector) = (1,1,0,0) + _BlinnPhongSpecularToggle("BlinnPhong高光开关",Float) = 0 + [HDR]_SpecularColor("BlinnPhong高光颜色",Color) = (1,1,1,1) + //-----------SixWayLight---------- + _RigRTBk("六路正方向图(P)",2D) = "white"{} + _RigLBtF("六路反方向图(N)",2D) = "white"{} + _SixWayColorAbsorptionToggle("六路光颜色吸收开关",Float) = 0 + _SixWayInfo("x:六路吸收强度",Vector) = (0.5,0,0,0) + _SixWayEmissionRamp("六路自发光Ramp",2D) = "white"{} + [HDR]_SixWayEmissionColor("六路自发光颜色",Color) = (1,0.5,0,1) + + //-----MatCap------ + _MatCapToggle("MatCap开关",Float) = 0 + _MatCapTex("MatCap图",2D) = "white"{} + [HDR]_MatCapColor("MatCap颜色",Color) = (1,1,1,1) + _MatCapInfo("x:MatCap叠加和相乘过渡",Vector) = (1,0,0,0) +// _MatCapBlendMode("MatCap叠加模式",Float) = 0 + + //时间缩放影响开关---------- + [HideInInspector] _TimeMode("__TimeMode",float) = 0.0 + + _StencilWithoutPlayerToggle("剔除主角色开关",Float) = 0.0 + + // MaskMap----------- + _MaskRefineToggle("遮罩整体调整开关",Float) = 0 + _MaskRefineVec("遮罩整体调整:x:Pow,y:相乘,z:相加",Vector) = (1,1,0,0) + _MaskMap ("遮罩贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _MaskMap2 ("遮罩2贴图 xy:UV缩放 zw:UV偏移", 2D) = "white"{} + _MaskMap3 ("遮罩3贴图 xy:UV缩放 zw:UV偏移", 2D) = "white"{} + _MaskMapOffsetAnition("xy:遮罩偏移速度,zw:遮罩2偏移速度", vector) = (0,0,0,0) + _MaskMap3OffsetAnition("xy:遮罩3偏移速度", vector) = (0,0,0,0) + _MaskMapUVRotation ("遮罩旋转", Range(0, 360)) = 0.0 + _MaskDistortion_intensity ("遮罩扭曲强度", float) = 0.0 + _MaskMapRotationSpeed("遮罩旋转速度", float) = 0.0 + _MaskMapVec("x整体遮罩强度,y遮罩2旋转,z遮罩3旋转",Vector) = (1,0,0,0) + + _MaskMapGradientToggle("遮罩渐变模式",Float) = 0 + _MaskMapGradientCount("颜色映射数量",Integer) = 2 + _MaskMapGradientFloat0("x:MaskAlpha0,y:Pos0,z:MaskAlpha1,w:Pos1",Vector) = (0,0,1,1) + _MaskMapGradientFloat1("x:MaskAlpha2,y:Pos2,z:MaskAlpha3,w:Pos3",Vector) = (1,0,1,1) + _MaskMapGradientFloat2("x:MaskAlpha4,y:Pos4,z:MaskAlpha5,w:Pos5",Vector) = (1,0,1,1) + _MaskMap2GradientToggle("遮罩2渐变模式",Float) = 0 + _MaskMap2GradientCount("颜色映射数量",Integer) = 2 + _MaskMap2GradientFloat0("x:Mask2Alpha0,y:Pos0,z:Mask2Alpha1,w:Pos1",Vector) = (0,0,1,1) + _MaskMap2GradientFloat1("x:Mask2Alpha2,y:Pos2,z:Mask2Alpha3,w:Pos3",Vector) = (1,0,1,1) + _MaskMap2GradientFloat2("x:Mask2Alpha4,y:Pos4,z:Mask2Alpha5,w:Pos5",Vector) = (1,0,1,1) + _MaskMap3GradientToggle("遮罩3渐变模式",Float) = 0 + _MaskMap3GradientCount("颜色映射数量",Integer) = 2 + _MaskMap3GradientFloat0("x:Mask3Alpha0,y:Pos0,z:Mask3Alpha1,w:Pos1",Vector) = (0,0,1,1) + _MaskMap3GradientFloat1("x:Mask3Alpha2,y:Pos2,z:Mask3Alpha3,w:Pos3",Vector) = (1,0,1,1) + _MaskMap3GradientFloat2("x:Mask3Alpha4,y:Pos4,z:Mask3Alpha5,w:Pos5",Vector) = (1,0,1,1) + + _MaskPNoiseBlendOpacity("遮罩噪波图混合强度",Float) = 1 + + // 擦除---------------- + //[Header(ChaChu(Anima For CustomData.z).......)] + //[KeywordEnum(NoChange,XianXing, JingXiang, Self)] _ch ("ChaChu mode", Float) = 0 + [HideInInspector] _Chachu ("__Chachu_ignore", Float) = 0.0 + _EdgeFade ("EdgeFade_ignore", Range(0, 1)) = 0.05 + _XianXingCH_UVRota ("XianXingCH_UVRota_ignore", float) = 0 + _jingxiangCH_dire ("Direction_ignore", Range(0, 1)) = 0 + + // 漩涡 ------------------- + //[Toggle(_JIZUOBIAO)] _N121 ("JIZUOBIAO?", float) = 0 + [HideInInspector] _UTwirlEnabled ("__UTwirlEnabled", Float) = 0.0 + _TWParameter ("xy:旋转扭曲中心", vector) = (0.5, 0.5, 0, 0) + _TWStrength ("旋转扭曲强度", float) = 1 + + + // 极坐标 ------------------- + //[Toggle(_JIZUOBIAO)] _N121 ("JIZUOBIAO?", float) = 0 + [HideInInspector]_PolarCoordinatesEnabled ("__PolarCoordinatesEnabled", Float) = 0.0 + _PCCenter ("xy:极坐标中心 z:极坐标强度", vector) = (0.5, 0.5, 1, 0)//位置坐标用的前两个分量,z分量给强度。 + + // 噪波 -------------- + //[Toggle(_NOISEMAP)]_N ("NOISEMAP?", float) =0 + [HideInInspector] _ScreenDistortModeToggle("_ScreenDistortModeToggle",Float) = 0 + [HideInInspector] _DisableMainPassToggle("_ScreenDistortModeToggle",Float) = 0 + [HideInInspector] _DistortMode("_DistortMode",Float) = 0 + [HideInInspector] _noisemapEnabled ("__noisemapEnabled", Float) = 0.0 + [HideInInspector] _noiseMaskMap_Toggle ("__noiseMaskMap_Toggle", Float) = 0.0 + _RefractionIOR("折射率",Float) = 1.5 + _NoiseMap ("扭曲贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _NoiseMaskMap ("扭曲遮罩贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _NoiseMapUVRotation("扭曲旋转",Range(0,360)) = 0 + _NoiseOffset ("xy:扭曲偏移速度 ", vector) = (0, 0, 0, 0)//w分量为本地uv坐标到世界坐标的变化 + _TexDistortion_intensity ("主贴图扭曲强度", float) = 0.5 + _NoiseIntensity("整体扭曲强度",Float) = 1 + _ScreenDistortIntensity("屏幕扭曲强度",Float) = 1 + _DistortPNoiseBlendOpacity("扭曲噪波图混合强度",Float) = 1 + + + _ScreenDistortAlphaRefineToggle("屏幕扭曲Alpha调整开关",Float) = 0 + _ScreenDistortAlphaPow("屏幕扭曲AlphaPow",Float) = 1 + _ScreenDistortAlphaMulti("屏幕扭曲Alpha相乘",Float) = 1 + _ScreenDistortAlphaAdd("屏幕扭曲Alpha相加",Float) = 0 + _DistortionDirection ("扭曲方向xy, 色散强度z", vector) = (1,1,0,0) + _Distortion_Choraticaberrat_Toggle("扭曲色散开关_Toggle",Float) = 0 + _Distortion_Choraticaberrat_WithNoise_Toggle("色散受扭曲影响_Toggle",Float) = 1 + + // 流光 ---------- + //[Header(LiuGuang(Anima For CustomData.w).......)] + //[Toggle(_EMISSION)]_N1 ("EMISSION?", float) = 0 + [HideInInspector] _EmissionEnabled ("__EmissionEnabled", Float) = 0.0 + _EmissionMap ("流光贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _EmissionMapUVRotation ("流光贴图旋转", Range(0, 360)) = 0 + _Emi_Distortion_intensity ("流光贴图扭转强度", float) = 0 + _EmissionMapUVOffset ("xy:流光贴图偏移速度", vector) = (0, 0, 0, 0) + _EmissionSelfAlphaWeight ("__EmissionSelfAlphaWeight_ignore", float) = 0 + _uvRapSoft ("LiuuvRapSoft-ignore", Range(0, 1)) = 0 + [HDR]_EmissionMapColor ("流光贴图颜色_hdr", Color) = (1, 1, 1, 1) + _EmissionMapColorIntensity("流光颜色强度", float) = 1 + + //颜色渐变贴图-------- + _ColorBlendMap_Toggle("__ColorBlendMap_Toggle",Float) = 0 + _ColorBlendMap("颜色渐变贴图 xy:UV缩放 zw:UV偏移",2D) = "white"{} + [HDR]_ColorBlendColor("颜色渐变叠加_hdr",Color) = (1,1,1,1) + _ColorBlendMapOffset("xy:颜色渐变贴图偏移动画",Vector) = (0,0,0,0) + _ColorBlendAlphaMultiplyMode("颜色渐变Alpha相乘开关",Float) = 0 + _ColorBlendVec("x:颜色渐变扰动强度z:Alpha强度w:旋转",Vector) = (0,0,1,0) + + //颜色映射Ramp + _RampColorToggle("颜色映射开关",Float) = 0 + _RampColorSourceMode("Ramp来源模式",Float) = 0 + _RampColorBlendMode("Ramp颜色混合模式",Float) = 0 + _RampColorMap("颜色映射黑白图",2D) = "white"{} + _RampColor0("rgb:RampColor0,a:pos",Color) = (0,0,0,0) + _RampColor1("rgb:RampColor1,a:pos",Color) = (1,0,0,1) + _RampColor2("rgb:RampColor2,a:pos",Color) = (1,1,1,1) + _RampColor3("rgb:RampColor3,a:pos",Color) = (1,1,1,1) + _RampColor4("rgb:RampColor4,a:pos",Color) = (1,1,1,1) + _RampColor5("rgb:RampColor5,a:pos",Color) = (1,1,1,1) + _RampColorAlpha0("x:RampColorAlpha0,y:Pos0,z:RampColorAlpha1,w:Pos1",Vector) = (1,0,1,1) + _RampColorAlpha1("x:RampColorAlpha2,y:Pos2,z:RampColorAlpha3,w:Pos3",Vector) = (1,0,1,1) + _RampColorAlpha2("x:RampColorAlpha4,y:Pos4,z:RampColorAlpha5,w:Pos5",Vector) = (1,0,1,1) + _RampColorCount("颜色映射数量",Integer) = 2 + [HDR]_RampColorBlendColor("颜色映射叠加颜色_hdr",Color) = (1,1,1,1) + _RampColorMapOffset("xy:颜色映射贴图偏移动画,w:旋转",Vector) = (0,0,0,0) + + + // Rongjie ------------------ + // [Header(RongJie(Anima For CustomData.y).......)] + // [Toggle(_DISSOLVE)]_RJ ("RONGJIE?", float) = 0 + _Dissolve ("x:溶解强度 y:溶解值Pow z:过程溶解强度 w:溶解硬软度", vector) = (0.5, 1, 1, 0.1) + _DissolveMap("溶解贴图 xy:UV缩放 zw:UV偏移",2D) = "grey"{} + _DissolveMaskMap("局部溶解蒙版 xy:UV缩放 zw:UV偏移",2D) = "white"{} + _DissolveMaskMode("溶解遮罩模式", Float) = 0 + _DissolveOffsetRotateDistort("xy:溶解贴图偏移速度 z:溶解贴图旋转",Vector) = (0,0,0,0) + [HDR]_DissolveLineColor("溶解描边颜色_hdr",Color) = (1,0,0,1) + _DissolveVoronoi_Vec("xy:噪波1缩放,zw:噪波2缩放",Vector) = (1,1,2,2) + _DissolveVoronoi_Vec2("x:噪波1和噪波2混合系数(圆尖),y:噪波整体和溶解贴图混合系数,z:噪波1速度,w:噪波2速度",Vector) = (1,1,2,2) + _DissolveVoronoi_Vec3("xy:噪波1偏移速度,zw:噪波2偏移速度",Vector) = (0,0,0,0) + _DissolveVoronoi_Vec4("xy:噪波1偏移,zw:噪波2偏移",Vector) = (0,0,0,0) + _Dissolve_Vec2("x:Ramp位置偏移,y:Ramp范围",Vector) = (0.2,0.1,0,0) + _DissolveRampMap("溶解Ramp图",2D) = "white"{} + _DissolveRampColorBlendMode("溶解Ramp图混合模式",Float) = 0 + [HDR]_DissolveRampColor("溶解Ramp颜色_hdr",Color) = (1,1,1,1) + _DissolveLineMaskToggle("溶解描边开关",Float) = 0 + + _DissolveRampSourceMode("溶解Ramp来源模式",Float) = 0 + _DissolveRampColor0("rgb:DissolveRampColor0,a:pos",Color) = (1,0,0,0) + _DissolveRampColor1("rgb:DissolveRampColor1,a:pos",Color) = (0,0,0,1) + _DissolveRampColor2("rgb:DissolveRampColor2,a:pos",Color) = (1,1,1,1) + _DissolveRampColor3("rgb:DissolveRampColor3,a:pos",Color) = (1,1,1,1) + _DissolveRampColor4("rgb:DissolveRampColor4,a:pos",Color) = (1,1,1,1) + _DissolveRampColor5("rgb:DissolveRampColor5,a:pos",Color) = (1,1,1,1) + _DissolveRampAlpha0("x:DissolveRampAlpha0,y:Pos0,z:DissolveRampAlpha1,w:Pos1",Vector) = (1,0,1,1) + _DissolveRampAlpha1("x:DissolveRampAlpha2,y:Pos2,z:DissolveRampAlpha3,w:Pos3",Vector) = (1,0,1,1) + _DissolveRampAlpha2("x:DissolveRampAlpha4,y:Pos4,z:DissolveRampAlpha5,w:Pos5",Vector) = (1,0,1,1) + _DissolveRampCount("溶解Ramp映射数量",Integer) = 2 + _DissolvePNoiseBlendOpacity("溶解噪波图混合强度",Float) = 1 + + _SharedUVToggle("公共UV开关",Float) = 0 + _SharedUV_ST("公共UVTillingOffset",Vector) = (1,1,0,0) + _SharedUV_Vec("xy:公共UV偏移速度,z:旋转,w:旋转速度",Vector) = (0,0,0,0) +// _SharedUV_Distort_Intensity("扭曲强度",Float) = 0 +// sharedUVDistortionIntensityRangeVec("_SharedUV_Distort_Intensity",Vector) = (-1,1,0,0) + + + _CustomData1X ("ignore", float) = 0 + _CustomData1Y ("ignore", float) = 0 + //因为希望本Shader兼容CanvasRender,由于Canvas渲染只会传递TEXCOORD通道的xy分量(zw分量忽略)的特性,所以强制让CustomedData只传递xy分量。 + _CustomData2X ("ignore", float) = 0 + + // ------------------------------------- + // Particle specific 属于粒子特殊的属性 + [ToggleOff] _CustomData ("__CustomData_Toggle", Float) = 0.0 //Toggleoff 和 Toggle 的区别 + [ToggleOff] _FlipbookBlending ("__flipbookblending_Toggle", Float) = 0.0 //Toggleoff 和 Toggle 的区别 +// _SoftParticlesNearFadeDistance ("Soft Particles Near Fade", Float) = 0.0 +// _SoftParticlesFarFadeDistance ("Soft Particles Far Fade", Float) = 1.0 + //[Toggle] _Fading ("Fading? =Default(1,2,0,0)", Float) = 0.0 + _CameraNearFadeDistance ("Camera Near Fade-ignore", Float) = 1.0 + _CameraFarFadeDistance ("Camera Far Fade-ignore", Float) = 2.0 + //临时 + _fogintensity ("雾影响强度", Range(0, 1)) = 1 + // ------------------------------------- + // Hidden properties - Generic 通用的隐藏属性 + _AdditiveToPreMultiplyAlphaLerp("相加到预乘混合",Range(0,1)) = 0.0 + [HideInInspector] _Blend ("__mode-ignore", Float) = 0.0 + [HideInInspector] _AlphaClip ("__clip-ignore", Float) = 0.0 + [HideInInspector] _SrcBlend ("__src-ignore", Float) = 1.0 + [HideInInspector] _DstBlend ("__dst-ignore", Float) = 0.0 + [HideInInspector] _Cull ("__cull-ignore", Float) = 2.0 + [HideInInspector] _ZTest ("__ztest-ignore", Float) = 4.0 //默认值LEqual + [HideInInspector] _ZWrite("__ZWrite-ignore", Float) = 0 //默认值LEqual + // [HideInInspector] _ZTestt ("__ztestt", Float) = 4.0//雨轩:注释掉了。。。这是个什么鬼。。。 + + _CustomStencilTest ("__CustomStencilTest-ignore", Float) = 0 + _StencilKeyIndex("__StencilKeyIndex-ignore",Float) = 0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp ("__StencilComp-ignore", Float) = 8 + _Stencil("Stencil ID-ignore", Float) = 0 + [Enum(UnityEngine.Rendering.StencilOp)]_StencilOp("Stencil Operation-ignore", Float) = 0 + _StencilWriteMask ("Stencil Write Mask-ignore", Float) = 255 + _StencilReadMask ("Stencil Read Mask-ignore", Float) = 255 + _ColorMask("Color Mask-ignore", Float) = 15 + + //[HideInInspector] _ZTestO ("__ztest0", Float) = 1.0 + _FresnelFadeDistance ("菲涅尔透明乘数", float) = 1 + _FresnelUnit("菲涅尔通用", Vector) = (0,0.5,1,0.5) + + _DepthOutline_Toggle("深度描边",Float) = 0 + [HDR]_DepthOutline_Color("深度描边颜色_hdr",Color) = (1,1,1,1) + _DepthOutline_Vec("菲涅尔深度描边参数",Vector) = (0,0.5,0,0) + _FresnelColorAffectByAlpha("菲涅尔颜色受Alpha影响",Float) = 1 +// _DepthOutline_withoutFresnel_Toggle("深度描边关闭菲涅尔",Float) = 0 +// _FresnelUnit2("菲涅尔通用2", Vector) = (1,1,0,0) + + _DepthDecal_Toggle("深度贴花",Float) = 0 + + _VertexOffset_Toggle("顶点偏移",Float) = 0 + _VertexOffset_Map("顶点偏移贴图",2D) = "white"{} + _VertexOffset_Vec("xy:顶点偏移动画z:顶点偏移强度",Vector) = (0,0,1,0) + _VertexOffset_NormalDir_Toggle("顶点偏移自定义方向开关",Float) = 0 + _VertexOffset_StartFromZero("顶点偏移从零开始开关",Float) = 0 + _VertexOffset_CustomDir("顶点偏移自定义方向",Vector) = (1,1,1,0) + + _VertexOffset_Mask_Toggle("顶点偏移遮罩开关",Float) = 0 + _VertexOffset_MaskMap("顶点偏移遮罩贴图",2D) = "white"{} + _VertexOffset_MaskMap_Vec("xy:顶点偏移遮罩动画z:顶点偏移遮罩强度",Vector) = (0,0,1,0) + + + _ParallaxMapping_Toggle("视差",Float) = 0 + _ParallaxMapping_Map("视差贴图",2D) = "white"{} + _ParallaxMapping_Intensity("视差强度",Float) = 0.05 + _ParallaxMapping_Vec("遮蔽视差层数 x:最小值,y:最大值",Vector) = (5,30,0,0) + + + // Particle specific 粒子特殊的隐藏属性 + [HideInInspector] _ColorMode ("_ColorMode", Float) = 0.0 + [HideInInspector] _BaseColorAddSubDiff ("_ColorMode", Vector) = (0, 0, 0, 0) + [HideInInspector] _SoftParticlesEnabled ("__softparticlesenabled", Float) = 0.0 + [HideInInspector] _CameraFadingEnabled ("__camerafadingenabled", Float) = 0.0 + [HideInInspector] _SoftParticleFadeParams ("xy:软粒子远近裁剪面", Vector) = (0, 0.5, 0, 0) + [HideInInspector] _CameraFadeParams ("__camerafadeparams_ignore", Vector) = (0, 0, 0, 0) + [HideInInspector] _IntersectEnabled("__IntersectEnabled_ignore",Float) = 0.0 + [HideInInspector] _IntersectRadius("__IntersectRadius_ignore",Float) = 0.3 + [HideInInspector] _IntersectColor("__IntersectColor_ignore",Color) = (1,1,1,1) + + + // Editmode props 编辑模式下的PropFlags? + [HideInInspector] _QueueBias ("Queue偏移_QueueBias", Float) =0 + + // ObsoleteProperties 弃用的属性???? + [HideInInspector] _FlipbookMode ("flipbook mode", Float) = 0 + // [HideInInspector] _Color ("color", Color) = (1, 1, 1, 1) + + [HideInInspector]_fresnelEnabled ("__fresnelEnabled", Float) = 0.0 + [NoScaleOffset]_FresnelHDRITex("__FresnelHDRITex_ignore",Cube) = "white"{} + [HDR]_FresnelColor ("菲涅尔颜色_hdr", COLOR) = (1, 1, 1, 1) + _FresnelRotation("菲涅尔方向偏移",vector) = (0,0,0,0.5) + _FresnelInOutSlider ("direction-ignore", Range(0, 1)) = 1 + _FrePower ("FrePower-ignore", Range(0,1)) = 0.5 + _FresnelSelfAlphaWeight("__FresnelSelfAlphaWeight-ignore",float) = 0 + //用于程序控制透明属性 + [HideInInspector] _ColorA ("ColorA-ignore", Color) = (1,1,1,1) + + _Portal_Toggle("模板视差开关",Float) = 0 + _Portal_MaskToggle("模板视差蒙版开关",Float) = 0 + + //基于深度的a通道控制 + [HideInInspector] _Fade("xy:近距离透明过度范围", Vector) = (2,4,0,0) + + [HideInInspector] _InspectorData("__InspectorData-ignore",vector) = (1,1,0,0) + + [Header(ZOffset)] + _ZOffset_Toggle("深度偏移_Toggle",Float) = 0 + _offsetFactor("深度偏移Sacle-ignore", range(-2000,2000)) = 0 + _offsetUnits("深度偏移单位距离-ignore", range(-2000,2000)) = 0 + + _WorldSpaceUVModeSelector("_WordSpaceUVModeSelector",Float) = 1 + _ObjectSpaceUVModeSelector("_ObjectSpaceUVModeSelector",Float) = 1 + + [HideInInspector] _W9ParticleShaderFlags("_W9ParticleShaderFlags", Integer) = 0 + [HideInInspector] _W9ParticleShaderFlags1("_W9ParticleShaderFlags1", Integer) = 0 + [HideInInspector] _W9ParticleShaderWrapFlags("_W9ParticleShaderWrapFlags", Integer) = 0 + [HideInInspector] _W9ParticleShaderWrapFlags2("_W9ParticleShaderWrapFlags2", Integer) = 0 + [HideInInspector] _W9ParticleCustomDataFlag0("_W9ParticleCustomDataFlag0", Integer) = 0 + [HideInInspector] _W9ParticleCustomDataFlag1("_W9ParticleCustomDataFlag1", Integer) = 0 + [HideInInspector] _W9ParticleCustomDataFlag2("_W9ParticleCustomDataFlag2", Integer) = 0 + [HideInInspector] _W9ParticleCustomDataFlag3("_W9ParticleCustomDataFlag3", Integer) = 0 + [HideInInspector] _UVModeFlag0("_UVModeFlag0", Integer) = 0 + [HideInInspector] _UVModeFlagType0("_UVModeFlagType0", Integer) = 0 + [HideInInspector] _W9ParticleShaderGUIFoldToggle("_W9ParticleShaderGUIFoldToggle", Integer) = 3//前2个开关默认打开 + [HideInInspector] _W9ParticleShaderGUIFoldToggle1("_W9ParticleShaderGUIFoldToggle1", Integer) = 255//这边默认全开 + [HideInInspector] _W9ParticleShaderGUIFoldToggle2("_W9ParticleShaderGUIFoldToggle2", Integer) = 255//这边默认全开 + [HideInInspector] _W9ParticleShaderColorChannelFlag("_W9ParticleShaderColorChannelFlag", Integer) = 3//默认主贴图开A通道 + [HideInInspector] _W9ParticleShaderPNoiseBlendFlag("_W9ParticleShaderPNoiseBlendFlag", Integer) = 0 + + + SaturabilityRangeVec("_Saturability",Vector) = (0,1,0,0) + TexDistortionintensityRangeVec("_TexDistortion_intensity",Vector) = (-1,1,0,0) + MaskDistortionIntensityRangeVec("_MaskDistortion_intensity",Vector) = (-2,2,0,0) + EmiDistortionIntensityRangeVec("_TexDistortion_intensity",Vector) = (-1,1,0,0) + BumpScaleRangeVec("_BumpScale",Vector) = (-1,1,0,0) + DissolveXRangeVec("_Dissolve.x",Vector) = (-1,2,0,0) + Dissolve2XRangeVec("_Dissolve_Vec2.x",Vector) = (0,1,0,0) + Dissolve2YRangeVec("_Dissolve_Vec2.y",Vector) = (0,1,0,0) + AlphaAllRangeVec("_AlphaAll",Vector) = (0,1,0,0) + _NoiseIntensityRangeVec("_NoiseIntensity",Vector) = (0,1,0,0) + _ScreenDistortIntensityRangeVec("_ScreenDistortIntensity",Vector) = (0,1,0,0) + _ParallaxMapping_IntensityRangeVec("_ParallaxMappingRangeVec",Vector) = (0,0.1,0,0) +// _offsetUnits("深度偏移单位距离-ignore", range(-2000,2000)) = 0 + + _NB_Debug_Mask("_NB_Debug_Mask",Float) = 0 + _NB_Debug_PNoise("_NB_Debug_PNoise",Float) = 0 + _NB_Debug_Dissolve("_NB_Debug_Dissolve",Float) = 0 + _NB_Debug_Distort("_NB_Debug_Dissolve",Float) = 0 + _NB_Debug_Fresnel("_NB_Debug_Fresnel",Float) = 0 + _NB_Debug_VertexOffset("_NB_Debug_VertexOffset",Float) = 0 + } + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Sphere" "CanUseSpriteAtlas"="True" } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + //BlendOp[_BlendOp] //考虑注释~ + Blend[_SrcBlend][_DstBlend] + ZWrite [_ZWrite]//粒子不写入深度缓冲 + ZTest[_ZTest] + + ColorMask [_ColorMask] + + // ------------------------------------------------------------------ + // 预渲染反面Pass,基本理念。先剔除正面棉片,渲染反面面片(一般在后),然后常规Pass再渲染正面(一般在前) + // 这样可以应对大部分的特效半透明渲染的次序问题。 + // URP下的多Pass渲染,需要使用特定的LightModeTag: + // https://zhuanlan.zhihu.com/p/469589277#:~:text=%E6%B3%A8%E6%84%8F%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%85%89%E7%85%A7pass%E7%9A%84%E5%85%89%E7%85%A7tag%E4%B8%BA%20%22LightMode%22%20%3D%20%22SRPDefaultUnlit%22%EF%BC%8C%E8%BF%99%E6%98%AF%E5%9B%A0%E4%B8%BA%E5%BF%85%E9%A1%BB%E8%AE%BE%E7%BD%AE%E4%B8%BA%E7%89%B9%E5%AE%9A%E7%9A%84%E5%87%A0%E4%B8%AALightMode%20%E6%89%8D%E8%83%BD%E6%AD%A3%E7%A1%AE%E8%A2%AB%E6%B8%B2%E6%9F%93%E3%80%82%E5%85%B7%E4%BD%93%E5%93%AA%E5%87%A0%E4%B8%AA%20LightMode%20%E8%A7%81URP%E5%8C%85%E9%87%8C%E7%9A%84%20Runtime/Passes%20%E9%87%8C%E7%9A%84%20DrawObjectsPass.cs%E8%84%9A%E6%9C%AC%EF%BC%8C%E9%87%8C%E9%9D%A2%E6%9C%89%E5%A6%82%E4%B8%8B%E4%BB%A3%E7%A0%81%EF%BC%9A + // 开关Pass,同样也需要用到LightTag + // https://blog.csdn.net/shaoy1234567/article/details/106494878 + + Pass + { + Tags + { + "LightMode" = "SRPDefaultUnlit" "Queue"="Opaque" + } + offset [_offsetFactor], [_offsetUnits] + Name "SRPDefaultUnlit" + Cull Front + + HLSLPROGRAM + #define PARTICLE + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + + #pragma exclude_renderers d3d11_9x + #pragma exclude_renderers d3d9 + + // #pragma enable_d3d11_debug_symbols // 保留D3D11调试符号 + + // ------------------------------------- + // Material Keywords + // #pragma shader_feature_local _ _SCREEN_DISTORT_MODE + #pragma shader_feature_local _ _DISTORT_REFRACTION + #pragma shader_feature_local _ _MASKMAP_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + //#pragma shader_feature_local _EMISSION //流光 + #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _PROGRAM_NOISE + //后续Test类的关键字要找机会排除 + #pragma shader_feature_local _DISSOLVE_EDITOR_TEST + #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local _SHARED_UV//公共UV + #pragma shader_feature_local _ _VAT _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _VAT_HOUDINI _VAT_TYFLOW + #pragma shader_feature_local_vertex _ _HOUDINI_VAT_SOFTBODY _HOUDINI_VAT_RIGIDBODY _HOUDINI_VAT_DYNAMIC_REMESH _HOUDINI_VAT_PARTICLE_SPRITE + #pragma shader_feature_local_vertex _ _TYFLOW_VAT_ABSOLUTE _TYFLOW_VAT_RELATIVE _TYFLOW_VAT_SKIN_R _TYFLOW_VAT_SKIN_PR _TYFLOW_VAT_SKIN_PRSAVE _TYFLOW_VAT_SKIN_PRSXYZ + + //将光照和UI混用,达到节省Keywords的目的。 + #pragma multi_compile _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS//UI 2D遮罩 + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + + // #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + + #pragma shader_feature_local _ FRESNEL_CUBEMAP FRESNEL_REFLECTIONPROBE + + + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + #pragma shader_feature_local _NOISEMAP_NORMALIZEED + + #pragma shader_feature_local _DEPTH_DECAL + #pragma shader_feature_local _PARALLAX_MAPPING + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT _FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _ _NORMALMAP + #pragma shader_feature_local _ _MATCAP + #pragma shader_feature_local _ _SPECULAR_COLOR + #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + #pragma shader_feature_local _ NB_DEBUG_MASK NB_DEBUG_PNOISE NB_DEBUG_DISSOLVE NB_DEBUG_DISTORT NB_DEBUG_FRESNEL NB_DEBUG_VERTEX_OFFSET + + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + + // #if defined(_SOFTPARTICLES_ON) + // #define NEED_EYE_DEPTH + // #endif + + #define PARTICLE_BACKFACE_PASS + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + // #include "UnityCG.cginc" + // #include "AutoLight.cginc" + // #include "UnityUI.cginc" + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + + #include "HLSL/ParticlesUnlitForwardPassNew.hlsl" + + ENDHLSL + + } + + // ------------------------------------------------------------------ + // Forward pass. + Pass + { + Tags + { + "LightMode" = "UniversalForward" + } //Queue设置是希望特效渲染在场景透明物体前面 + offset [_offsetFactor], [_offsetUnits] + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + //20240228 target3.0 顶点着色器限制16个输出。提高版本 + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + // ------------------------------------- + // Material Keywords + + // #pragma enable_d3d11_debug_symbols // 保留D3D11调试符号 + + // #pragma shader_feature_local _ _SCREEN_DISTORT_MODE + #pragma shader_feature_local _ _DISTORT_REFRACTION + #pragma shader_feature_local _ _MASKMAP_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + //#pragma shader_feature_local _EMISSION //流光 + #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _PROGRAM_NOISE + //后续Test类的关键字要找机会排除 + #pragma shader_feature_local _DISSOLVE_EDITOR_TEST + #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local _SHARED_UV//公共UV + #pragma shader_feature_local _ _VAT _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _VAT_HOUDINI _VAT_TYFLOW + #pragma shader_feature_local_vertex _ _HOUDINI_VAT_SOFTBODY _HOUDINI_VAT_RIGIDBODY _HOUDINI_VAT_DYNAMIC_REMESH _HOUDINI_VAT_PARTICLE_SPRITE + #pragma shader_feature_local_vertex _ _TYFLOW_VAT_ABSOLUTE _TYFLOW_VAT_RELATIVE _TYFLOW_VAT_SKIN_R _TYFLOW_VAT_SKIN_PR _TYFLOW_VAT_SKIN_PRSAVE _TYFLOW_VAT_SKIN_PRSXYZ + + + #pragma multi_compile_local _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //UI 2D遮罩 + // #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + + #pragma shader_feature_local _ FRESNEL_CUBEMAP FRESNEL_REFLECTIONPROBE + + + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + #pragma shader_feature_local _NOISEMAP_NORMALIZEED + + #pragma shader_feature_local _DEPTH_DECAL + #pragma shader_feature_local _PARALLAX_MAPPING + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT _FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _ _NORMALMAP + #pragma shader_feature_local _ _MATCAP + #pragma shader_feature_local _ _SPECULAR_COLOR + #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + + #pragma shader_feature_local _ NB_DEBUG_MASK NB_DEBUG_PNOISE NB_DEBUG_DISSOLVE NB_DEBUG_DISTORT NB_DEBUG_FRESNEL NB_DEBUG_VERTEX_OFFSET + + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera + // depth texture. + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/ParticlesUnlitForwardPassNew.hlsl" + + + ENDHLSL + + } + + Pass + { + Name "DepthOnly" + Tags + { + "LightMode" = "DepthOnly" + } + + Blend One Zero + ZWrite On + ZTest LEqual + ColorMask R + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + #define _FX_LIGHT_MODE_UNLIT + #define NB_DEPTH_ONLY_PASS + + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _SHARED_UV + #pragma shader_feature_local _ _VAT _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _VAT_HOUDINI _VAT_TYFLOW + #pragma shader_feature_local_vertex _ _HOUDINI_VAT_SOFTBODY _HOUDINI_VAT_RIGIDBODY _HOUDINI_VAT_DYNAMIC_REMESH _HOUDINI_VAT_PARTICLE_SPRITE + #pragma shader_feature_local_vertex _ _TYFLOW_VAT_ABSOLUTE _TYFLOW_VAT_RELATIVE _TYFLOW_VAT_SKIN_R _TYFLOW_VAT_SKIN_PR _TYFLOW_VAT_SKIN_PRSAVE _TYFLOW_VAT_SKIN_PRSXYZ + #pragma shader_feature_local _ALPHATEST_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local _UNSCALETIME + #pragma shader_feature_local _SCRIPTABLETIME + #pragma shader_feature_local _NOISEMAP_NORMALIZEED + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/ParticlesUnlitForwardPassNew.hlsl" + + ENDHLSL + } + + Pass + { + Name "ShadowCaster" + Tags + { + "LightMode" = "ShadowCaster" + } + + Blend One Zero + ZWrite On + ZTest LEqual + ColorMask 0 + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + #define _FX_LIGHT_MODE_UNLIT + #define NB_SHADOW_CASTER_PASS + + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _SHARED_UV + #pragma shader_feature_local _ _VAT _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _VAT_HOUDINI _VAT_TYFLOW + #pragma shader_feature_local_vertex _ _HOUDINI_VAT_SOFTBODY _HOUDINI_VAT_RIGIDBODY _HOUDINI_VAT_DYNAMIC_REMESH _HOUDINI_VAT_PARTICLE_SPRITE + #pragma shader_feature_local_vertex _ _TYFLOW_VAT_ABSOLUTE _TYFLOW_VAT_RELATIVE _TYFLOW_VAT_SKIN_R _TYFLOW_VAT_SKIN_PR _TYFLOW_VAT_SKIN_PRSAVE _TYFLOW_VAT_SKIN_PRSXYZ + #pragma shader_feature_local _ALPHATEST_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local _UNSCALETIME + #pragma shader_feature_local _SCRIPTABLETIME + #pragma shader_feature_local _NOISEMAP_NORMALIZEED + + #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/ParticlesUnlitForwardPassNew.hlsl" + + ENDHLSL + } + + // ------------------------------------------------------------------ + // Distort pass. + Pass + { + Tags{ + "LightMode" = "NBCameraOpaqueDistortPass" + } //Queue设置是希望特效渲染在场景透明物体前面 + offset [_offsetFactor], [_offsetUnits] + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + //20240228 target3.0 顶点着色器限制16个输出。提高版本 + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + // ------------------------------------- + // Material Keywords + + // #pragma enable_d3d11_debug_symbols // 保留D3D11调试符号 + + #define _SCREEN_DISTORT_MODE + #define _CAMERA_OPAQUE_DISTORT_PASS + #pragma shader_feature_local _ _DISTORT_REFRACTION + #pragma shader_feature_local _ _MASKMAP_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + //#pragma shader_feature_local _EMISSION //流光 + // #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _PROGRAM_NOISE + //后续Test类的关键字要找机会排除 + #pragma shader_feature_local _DISSOLVE_EDITOR_TEST + // #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + // #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local _SHARED_UV//公共UV + + + // #pragma multi_compile_local _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //UI 2D遮罩 + // #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + + #pragma shader_feature_local _ FRESNEL_CUBEMAP FRESNEL_REFLECTIONPROBE + + + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + #pragma shader_feature_local _NOISEMAP_NORMALIZEED + + #pragma shader_feature_local _DEPTH_DECAL + // #pragma shader_feature_local _PARALLAX_MAPPING + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT //_FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _ _NORMALMAP + // #pragma shader_feature_local _ _MATCAP + // #pragma shader_feature_local _ _SPECULAR_COLOR + // #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera + // depth texture. + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/ParticlesUnlitForwardPassNew.hlsl" + + + ENDHLSL + + } + +// ------------------------------------------------------------------ + // Distort pass. + Pass + { + Tags{ + "LightMode" = "NBDeferredDistortPass" + } //Queue设置是希望特效渲染在场景透明物体前面 + offset [_offsetFactor], [_offsetUnits] + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + //20240228 target3.0 顶点着色器限制16个输出。提高版本 + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + // ------------------------------------- + // Material Keywords + + // #pragma enable_d3d11_debug_symbols // 保留D3D11调试符号 + + #define _SCREEN_DISTORT_MODE + #define _DEFERRED_DISTORT_PASS + #pragma shader_feature_local _ _DISTORT_REFRACTION + + #pragma shader_feature_local _ _MASKMAP_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + //#pragma shader_feature_local _EMISSION //流光 + // #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _PROGRAM_NOISE + //后续Test类的关键字要找机会排除 + #pragma shader_feature_local _DISSOLVE_EDITOR_TEST + // #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + // #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local _SHARED_UV//公共UV + + + // #pragma multi_compile_local _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //UI 2D遮罩 + // #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + + #pragma shader_feature_local _ FRESNEL_CUBEMAP FRESNEL_REFLECTIONPROBE + + + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + #pragma shader_feature_local _NOISEMAP_NORMALIZEED + + #pragma shader_feature_local _DEPTH_DECAL + // #pragma shader_feature_local _PARALLAX_MAPPING + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT //_FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _ _NORMALMAP + // #pragma shader_feature_local _ _MATCAP + // #pragma shader_feature_local _ _SPECULAR_COLOR + // #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera + // depth texture. + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/ParticlesUnlitForwardPassNew.hlsl" + + + ENDHLSL + + } + + // ------------------------------------------------------------------ + // Forward pass. + Pass + { + Tags + { + "LightMode" = "Universal2D" + } //Queue设置是希望特效渲染在场景透明物体前面 + offset [_offsetFactor], [_offsetUnits] + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + //20240228 target3.0 顶点着色器限制16个输出。提高版本 + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + // ------------------------------------- + // Material Keywords + + // #pragma enable_d3d11_debug_symbols // 保留D3D11调试符号 + + #pragma shader_feature_local _ _SCREEN_DISTORT_MODE + #pragma shader_feature_local _ _MASKMAP_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + //#pragma shader_feature_local _EMISSION //流光 + #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _PROGRAM_NOISE + //后续Test类的关键字要找机会排除 + #pragma shader_feature_local _DISSOLVE_EDITOR_TEST + #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local _SHARED_UV//公共UV + + + #pragma multi_compile_local _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //UI 2D遮罩 + // #pragma shader_feature_local _ _CH_XIANXING _CH_JINGXIANG _CH_SELF //线性擦除 径向擦除 mask擦除 + #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + + #pragma shader_feature_local _ FRESNEL_CUBEMAP FRESNEL_REFLECTIONPROBE + + + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + // #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + #pragma shader_feature_local _NOISEMAP_NORMALIZEED + + // #pragma shader_feature_local _DEPTH_DECAL + // #pragma shader_feature_local _PARALLAX_MAPPING + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT //_FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _ _NORMALMAP + // #pragma shader_feature_local _ _MATCAP + // #pragma shader_feature_local _ _SPECULAR_COLOR + // #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera + // depth texture. + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + + #include "HLSL/ParticlesUnlitForwardPassNew.hlsl" + + + ENDHLSL + + } + } + + CustomEditor "NBShaderEditor.ParticleBaseGUI" +} diff --git a/Packages/NB_FX/NBShaders/Shader/ParticleBase.shader.meta b/Packages/NB_FX/NBShaders/Shader/ParticleBase.shader.meta new file mode 100644 index 00000000..8058ad6c --- /dev/null +++ b/Packages/NB_FX/NBShaders/Shader/ParticleBase.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7184a95c20fc1a441a8815af4c795ccd +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2.meta b/Packages/NB_FX/NBShaders2.meta new file mode 100644 index 00000000..323e61ea --- /dev/null +++ b/Packages/NB_FX/NBShaders2.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dbb9a18213f2fff4b86e60510703bec7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor.meta b/Packages/NB_FX/NBShaders2/Editor.meta new file mode 100644 index 00000000..4992326b --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 95e40beb3a78e8144b5af938f9e6b2e6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel.meta new file mode 100644 index 00000000..b90f48bd --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fb8ba48b3d36342e3bd039e124cae415 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets.meta new file mode 100644 index 00000000..68bda6b0 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a87eea7424634acb8293156f600ae92a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets/NBShaderDefaultFeatureLevels.asset b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets/NBShaderDefaultFeatureLevels.asset new file mode 100644 index 00000000..33ec77cf --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets/NBShaderDefaultFeatureLevels.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed6294ea8daafcbb144e6ca2d5422c4792ea882b6860838bd31a6cdb823f23e4 +size 4496 diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets/NBShaderDefaultFeatureLevels.asset.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets/NBShaderDefaultFeatureLevels.asset.meta new file mode 100644 index 00000000..e187a7ff --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/LevelAssets/NBShaderDefaultFeatureLevels.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 78855065a5a548f490982968a0e01781 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderEditorQualityTierWatcher.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderEditorQualityTierWatcher.cs new file mode 100644 index 00000000..e1a6491f --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderEditorQualityTierWatcher.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor.FeatureLevel +{ + [InitializeOnLoad] + internal static class NBShaderEditorQualityTierWatcher + { + private const string UndoApplyLoadedTier = "Apply NBShader Quality Tier"; + private const string UndoApplyProjectTier = "Apply NBShader Quality Tier To Project Materials"; + + private static int s_LastQualityLevel; + private static bool s_DialogQueued; + + static NBShaderEditorQualityTierWatcher() + { + s_LastQualityLevel = QualitySettings.GetQualityLevel(); + EditorApplication.update += WatchQualityLevel; + } + + internal static void ApplyCurrentQualityTierToLoadedMaterials() + { + NBShaderFeatureTier tier; + string qualityName; + ResolveCurrentQualityTier(out tier, out qualityName); + var count = ApplyTierToLoadedMaterials(tier); + Debug.LogFormat( + "Applied NBShader2 tier {0} from Unity Quality '{1}' to {2} loaded material(s).", + tier, + qualityName, + count); + } + + internal static void ApplyCurrentQualityTierToProjectMaterials() + { + NBShaderFeatureTier tier; + string qualityName; + ResolveCurrentQualityTier(out tier, out qualityName); + var count = ApplyTierToProjectMaterials(tier); + Debug.LogFormat( + "Applied NBShader2 tier {0} from Unity Quality '{1}' to {2} project material asset(s).", + tier, + qualityName, + count); + } + + private static void WatchQualityLevel() + { + if (Application.isBatchMode || + EditorApplication.isCompiling || + EditorApplication.isUpdating || + EditorApplication.isPlayingOrWillChangePlaymode || + s_DialogQueued) + { + return; + } + + var current = QualitySettings.GetQualityLevel(); + if (current == s_LastQualityLevel) + return; + + s_LastQualityLevel = current; + s_DialogQueued = true; + EditorApplication.delayCall += PromptForQualityTierSync; + } + + private static void PromptForQualityTierSync() + { + s_DialogQueued = false; + if (Application.isBatchMode || + EditorApplication.isCompiling || + EditorApplication.isUpdating || + EditorApplication.isPlayingOrWillChangePlaymode) + { + return; + } + + NBShaderFeatureTier tier; + string qualityName; + ResolveCurrentQualityTier(out tier, out qualityName); + + var syncLoaded = EditorUtility.DisplayDialog( + "NBShader2 Feature Tier", + string.Format( + "Unity Quality has switched to '{0}'.\n\nSync currently loaded NBShader2 materials to tier {1}?", + qualityName, + tier), + "Sync Loaded", + "Skip"); + if (!syncLoaded) + return; + + var loadedCount = ApplyTierToLoadedMaterials(tier); + + var syncProject = EditorUtility.DisplayDialog( + "NBShader2 Feature Tier", + string.Format( + "Applied tier {0} to {1} loaded NBShader2 material(s).\n\nScan Assets and write current keyword/pass state for all NBShader2 material assets?", + tier, + loadedCount), + "Scan Assets", + "Loaded Only"); + if (syncProject) + { + var projectCount = ApplyTierToProjectMaterials(tier); + Debug.LogFormat( + "Applied NBShader2 tier {0} from Unity Quality '{1}' to {2} project material asset(s).", + tier, + qualityName, + projectCount); + } + } + + private static void ResolveCurrentQualityTier(out NBShaderFeatureTier tier, out string qualityName) + { + qualityName = GetCurrentQualityName(); + if (!NBShaderFeatureLevelProjectSettings.instance.TryGetTierForQualityNameNoSave(qualityName, out tier)) + tier = NBShaderFeatureTier.Ultra; + } + + private static string GetCurrentQualityName() + { + var names = QualitySettings.names; + var index = QualitySettings.GetQualityLevel(); + if (names == null || index < 0 || index >= names.Length) + return string.Empty; + return names[index]; + } + + private static int ApplyTierToLoadedMaterials(NBShaderFeatureTier tier) + { + var materials = Resources.FindObjectsOfTypeAll(); + var editableMaterials = new List(); + var seen = new HashSet(); + for (var i = 0; i < materials.Length; i++) + { + var material = materials[i]; + if (!CanMutateMaterial(material) || !seen.Add(material.GetInstanceID())) + continue; + editableMaterials.Add(material); + } + + if (editableMaterials.Count == 0) + return 0; + + var undoGroup = Undo.GetCurrentGroup(); + Undo.SetCurrentGroupName(UndoApplyLoadedTier); + for (var i = 0; i < editableMaterials.Count; i++) + ApplyTierToMaterial(editableMaterials[i], tier, UndoApplyLoadedTier); + Undo.CollapseUndoOperations(undoGroup); + return editableMaterials.Count; + } + + private static int ApplyTierToProjectMaterials(NBShaderFeatureTier tier) + { + var guids = AssetDatabase.FindAssets("t:Material", new[] { "Assets" }); + var changed = 0; + var undoGroup = Undo.GetCurrentGroup(); + Undo.SetCurrentGroupName(UndoApplyProjectTier); + + try + { + for (var i = 0; i < guids.Length; i++) + { + if (EditorUtility.DisplayCancelableProgressBar( + "NBShader2 Feature Tier", + string.Format("Scanning material {0}/{1}", i + 1, guids.Length), + guids.Length > 0 ? (float)i / guids.Length : 1f)) + { + break; + } + + var path = AssetDatabase.GUIDToAssetPath(guids[i]); + var material = AssetDatabase.LoadAssetAtPath(path); + if (!CanMutateMaterial(material)) + continue; + + if (ApplyTierToMaterial(material, tier, UndoApplyProjectTier)) + { + AssetDatabase.SaveAssetIfDirty(material); + changed++; + } + } + } + finally + { + EditorUtility.ClearProgressBar(); + Undo.CollapseUndoOperations(undoGroup); + } + + return changed; + } + + private static bool CanMutateMaterial(Material material) + { + if (!NBShaderMaterialIntentResolver.IsNBShaderMaterial(material)) + return false; + + var flags = material.hideFlags; + if ((flags & HideFlags.NotEditable) != 0 || + (flags & HideFlags.HideAndDontSave) != 0) + { + return false; + } + + if (!EditorUtility.IsPersistent(material)) + return true; + + var path = AssetDatabase.GetAssetPath(material); + return !string.IsNullOrEmpty(path) && path.StartsWith("Assets/", StringComparison.Ordinal); + } + + private static bool ApplyTierToMaterial( + Material material, + NBShaderFeatureTier tier, + string undoName) + { + Undo.RecordObject(material, undoName); + bool changed; + if (!NBShaderFeatureLevelMaterialApplier.Apply(material, tier, true, true, out changed)) + return false; + + if (changed) + EditorUtility.SetDirty(material); + + return changed; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderEditorQualityTierWatcher.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderEditorQualityTierWatcher.cs.meta new file mode 100644 index 00000000..3f21b5af --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderEditorQualityTierWatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48ae002b228442d4a26f69f91cef7810 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildInfo.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildInfo.cs new file mode 100644 index 00000000..99f265b6 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildInfo.cs @@ -0,0 +1,749 @@ +using System; +using System.Collections.Generic; +using NBShader; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NBShaders2.Editor.FeatureLevel +{ + public enum NBShaderBuildInfoMode + { + TierAndPass = 0, + ExactMaterialVariants = 1 + } + + public sealed class NBShaderBuildInfoSet + { + private readonly NBShaderMaterialBuildInfo[] m_Materials; + private readonly NBShaderVariantBuildInfo[] m_Variants; + private readonly string[] m_AllowedManagedKeywords; + private readonly string[] m_AllowedPassFeatures; + private readonly string[] m_IncludedPassNames; + + public readonly NBShaderFeatureTier tier; + public readonly NBShaderBuildInfoMode mode; + + public NBShaderMaterialBuildInfo[] materials { get { return (NBShaderMaterialBuildInfo[])m_Materials.Clone(); } } + public NBShaderVariantBuildInfo[] variants { get { return (NBShaderVariantBuildInfo[])m_Variants.Clone(); } } + public string[] allowedManagedKeywords { get { return (string[])m_AllowedManagedKeywords.Clone(); } } + public string[] allowedPassFeatures { get { return (string[])m_AllowedPassFeatures.Clone(); } } + public string[] includedPassNames { get { return (string[])m_IncludedPassNames.Clone(); } } + public bool hasMaterials { get { return m_Materials.Length > 0; } } + + public NBShaderBuildInfoSet( + NBShaderFeatureTier tier, + NBShaderBuildInfoMode mode, + NBShaderMaterialBuildInfo[] materials, + string[] allowedManagedKeywords, + string[] allowedPassFeatures = null) + { + this.tier = tier; + this.mode = mode; + m_Materials = materials != null ? (NBShaderMaterialBuildInfo[])materials.Clone() : new NBShaderMaterialBuildInfo[0]; + m_AllowedManagedKeywords = allowedManagedKeywords != null ? (string[])allowedManagedKeywords.Clone() : new string[0]; + m_AllowedPassFeatures = NBShaderBuildInfoUtility.ToCatalogOrderedPassFeatures(allowedPassFeatures); + m_Variants = BuildUniqueVariants(m_Materials); + m_IncludedPassNames = BuildIncludedPassNames(m_Materials); + } + + private static NBShaderVariantBuildInfo[] BuildUniqueVariants(NBShaderMaterialBuildInfo[] materials) + { + var result = new List(); + var keys = new HashSet(StringComparer.Ordinal); + for (var i = 0; i < materials.Length; i++) + { + var material = materials[i]; + if (material == null) + continue; + + var materialVariants = material.variants; + for (var v = 0; v < materialVariants.Length; v++) + { + var variant = materialVariants[v]; + if (variant == null) + continue; + + var key = variant.GetStableKey(); + if (keys.Add(key)) + result.Add(variant); + } + } + + return result.ToArray(); + } + + private static string[] BuildIncludedPassNames(NBShaderMaterialBuildInfo[] materials) + { + var result = new List(); + var set = new HashSet(StringComparer.Ordinal); + for (var i = 0; i < materials.Length; i++) + { + var material = materials[i]; + if (material == null) + continue; + + var passNames = material.includedPassNames; + for (var p = 0; p < passNames.Length; p++) + { + var passName = passNames[p]; + if (!string.IsNullOrEmpty(passName) && set.Add(passName)) + result.Add(passName); + } + } + + return result.ToArray(); + } + } + + public sealed class NBShaderMaterialBuildInfo + { + private readonly string[] m_EffectiveKeywords; + private readonly string[] m_StrippedManagedKeywords; + private readonly string[] m_AllowedManagedKeywords; + private readonly string[] m_AllowedPassFeatures; + private readonly NBShaderPassBuildInfo[] m_Passes; + private readonly NBShaderVariantBuildInfo[] m_Variants; + private readonly string[] m_IncludedPassNames; + + public readonly Material material; + public readonly Shader shader; + public readonly NBShaderFeatureTier tier; + public readonly NBShaderBuildInfoMode mode; + + public string[] effectiveKeywords { get { return (string[])m_EffectiveKeywords.Clone(); } } + public string[] strippedManagedKeywords { get { return (string[])m_StrippedManagedKeywords.Clone(); } } + public string[] allowedManagedKeywords { get { return (string[])m_AllowedManagedKeywords.Clone(); } } + public string[] allowedPassFeatures { get { return (string[])m_AllowedPassFeatures.Clone(); } } + public NBShaderPassBuildInfo[] passes { get { return (NBShaderPassBuildInfo[])m_Passes.Clone(); } } + public NBShaderVariantBuildInfo[] variants { get { return (NBShaderVariantBuildInfo[])m_Variants.Clone(); } } + public string[] includedPassNames { get { return (string[])m_IncludedPassNames.Clone(); } } + + public NBShaderMaterialBuildInfo( + Material material, + NBShaderFeatureTier tier, + NBShaderBuildInfoMode mode, + string[] allowedManagedKeywords, + string[] effectiveKeywords, + string[] strippedManagedKeywords, + NBShaderPassBuildInfo[] passes, + string[] allowedPassFeatures = null) + { + this.material = material; + shader = material != null ? material.shader : null; + this.tier = tier; + this.mode = mode; + m_AllowedManagedKeywords = NBShaderBuildInfoUtility.ToCatalogOrderedManagedKeywords(allowedManagedKeywords); + m_AllowedPassFeatures = NBShaderBuildInfoUtility.ToCatalogOrderedPassFeatures(allowedPassFeatures); + m_EffectiveKeywords = NBShaderBuildInfoUtility.ToCatalogOrderedManagedKeywords(effectiveKeywords); + m_StrippedManagedKeywords = NBShaderBuildInfoUtility.ToCatalogOrderedManagedKeywords(strippedManagedKeywords); + m_Passes = passes != null ? (NBShaderPassBuildInfo[])passes.Clone() : new NBShaderPassBuildInfo[0]; + m_IncludedPassNames = BuildIncludedPassNames(m_Passes); + m_Variants = BuildVariants(); + } + + private NBShaderVariantBuildInfo[] BuildVariants() + { + if (shader == null) + return new NBShaderVariantBuildInfo[0]; + + var result = new List(); + var materialKeywords = NBShaderBuildInfoUtility.GetCatalogExternalMaterialKeywords(material); + for (var i = 0; i < m_Passes.Length; i++) + { + var pass = m_Passes[i]; + if (pass == null || !pass.included) + continue; + + result.Add(new NBShaderVariantBuildInfo( + shader, + pass.passName, + pass.passType, + NBShaderBuildInfoUtility.BuildShaderVariantKeywordsForPass( + pass.passName, + pass.passType, + m_EffectiveKeywords, + materialKeywords))); + } + + return result.ToArray(); + } + + private static string[] BuildIncludedPassNames(NBShaderPassBuildInfo[] passes) + { + var result = new List(); + for (var i = 0; i < passes.Length; i++) + { + var pass = passes[i]; + if (pass != null && pass.included && !string.IsNullOrEmpty(pass.passName)) + result.Add(pass.passName); + } + + return result.ToArray(); + } + } + + public sealed class NBShaderPassBuildInfo + { + public readonly string passName; + public readonly PassType passType; + public readonly bool enabledByMaterial; + public readonly bool allowedByTier; + public readonly bool included; + public readonly string reason; + + public NBShaderPassBuildInfo( + string passName, + PassType passType, + bool enabledByMaterial, + bool allowedByTier, + bool included, + string reason) + { + this.passName = passName; + this.passType = passType; + this.enabledByMaterial = enabledByMaterial; + this.allowedByTier = allowedByTier; + this.included = included; + this.reason = reason; + } + } + + public sealed class NBShaderVariantBuildInfo + { + private readonly string[] m_Keywords; + + public readonly Shader shader; + public readonly string passName; + public readonly PassType passType; + public string[] keywords { get { return (string[])m_Keywords.Clone(); } } + + public NBShaderVariantBuildInfo(Shader shader, string passName, PassType passType, string[] keywords) + { + this.shader = shader; + this.passName = passName; + this.passType = passType; + m_Keywords = NBShaderBuildInfoUtility.ToShaderVariantOrderedKeywords(keywords); + } + + public string GetStableKey() + { + string shaderName = shader != null ? shader.name : string.Empty; + return shaderName + "|" + passName + "|" + passType + "|" + string.Join(";", m_Keywords); + } + } + + internal static class NBShaderBuildInfoUtility + { + public static PassType GetPassType(string passName) + { + if (passName == "SRPDefaultUnlit") + return PassType.ScriptableRenderPipelineDefaultUnlit; + if (passName == "ShadowCaster") + return PassType.ShadowCaster; + return PassType.ScriptableRenderPipeline; + } + + public static string[] FilterKeywordsForPass(string passName, PassType passType, IEnumerable keywords) + { + var declaredKeywords = GetDeclaredKeywords(passName, passType); + var result = new List(); + var source = ToCatalogOrderedManagedKeywords(keywords); + for (var i = 0; i < source.Length; i++) + { + var keyword = source[i]; + if (declaredKeywords.Contains(keyword)) + result.Add(keyword); + } + + return result.ToArray(); + } + + public static string[] BuildShaderVariantKeywordsForPass( + string passName, + PassType passType, + IEnumerable managedKeywords, + IEnumerable externalKeywords) + { + var declaredKeywords = GetDeclaredShaderVariantKeywords(passName, passType); + var source = new HashSet(StringComparer.Ordinal); + + var managed = ToCatalogOrderedManagedKeywords(managedKeywords); + for (var i = 0; i < managed.Length; i++) + { + var keyword = managed[i]; + source.Add(keyword); + if (string.Equals(keyword, "_FX_LIGHT_MODE_SIX_WAY", StringComparison.Ordinal)) + source.Add("EVALUATE_SH_VERTEX"); + } + + if (externalKeywords != null) + { + foreach (var keyword in externalKeywords) + { + if (IsCatalogExternalShaderKeyword(keyword)) + source.Add(keyword); + } + } + + var result = new List(); + for (var i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++) + { + var keyword = NBShaderFeatureCatalog.RawKeywords[i]; + if (source.Contains(keyword) && declaredKeywords.Contains(keyword)) + result.Add(keyword); + } + + for (var i = 0; i < CatalogExternalShaderKeywordOrder.Length; i++) + { + var keyword = CatalogExternalShaderKeywordOrder[i]; + if (source.Contains(keyword) && declaredKeywords.Contains(keyword)) + result.Add(keyword); + } + + return result.ToArray(); + } + + public static string[] GetCatalogExternalMaterialKeywords(Material material) + { + if (material == null || material.shaderKeywords == null || material.shaderKeywords.Length == 0) + return new string[0]; + + var result = new List(); + var source = new HashSet(material.shaderKeywords, StringComparer.Ordinal); + for (var i = 0; i < CatalogExternalShaderKeywordOrder.Length; i++) + { + var keyword = CatalogExternalShaderKeywordOrder[i]; + if (source.Contains(keyword)) + result.Add(keyword); + } + + return result.ToArray(); + } + + public static string[] ToCatalogOrderedManagedKeywords(IEnumerable keywords) + { + var set = new HashSet(StringComparer.Ordinal); + if (keywords != null) + { + foreach (var keyword in keywords) + { + if (NBShaderFeatureCatalog.IsManagedKeyword(keyword)) + set.Add(keyword); + } + } + + if (set.Count == 0) + return new string[0]; + + var result = new List(); + for (var i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++) + { + var keyword = NBShaderFeatureCatalog.RawKeywords[i]; + if (set.Contains(keyword)) + result.Add(keyword); + } + + return result.ToArray(); + } + + public static string[] ToShaderVariantOrderedKeywords(IEnumerable keywords) + { + var set = new HashSet(StringComparer.Ordinal); + if (keywords != null) + { + foreach (var keyword in keywords) + { + if (NBShaderFeatureCatalog.IsManagedKeyword(keyword) || + IsCatalogExternalShaderKeyword(keyword)) + { + set.Add(keyword); + } + } + } + + if (set.Count == 0) + return new string[0]; + + var result = new List(); + for (var i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++) + { + var keyword = NBShaderFeatureCatalog.RawKeywords[i]; + if (set.Contains(keyword)) + result.Add(keyword); + } + + for (var i = 0; i < CatalogExternalShaderKeywordOrder.Length; i++) + { + var keyword = CatalogExternalShaderKeywordOrder[i]; + if (set.Contains(keyword)) + result.Add(keyword); + } + + return result.ToArray(); + } + + public static string[] ToCatalogOrderedPassFeatures(IEnumerable passFeatures) + { + var set = new HashSet(StringComparer.Ordinal); + if (passFeatures != null) + { + foreach (var passFeature in passFeatures) + { + if (NBShaderPassFeatureCatalog.IsManagedPassFeature(passFeature)) + set.Add(passFeature); + } + } + + if (set.Count == 0) + return new string[0]; + + var result = new List(); + for (var i = 0; i < NBShaderPassFeatureCatalog.RawPassFeatureIds.Length; i++) + { + var passFeature = NBShaderPassFeatureCatalog.RawPassFeatureIds[i]; + if (set.Contains(passFeature)) + result.Add(passFeature); + } + + return result.ToArray(); + } + + public static bool ContainsPassName(string[] passNames, string passName) + { + if (passNames == null || string.IsNullOrEmpty(passName)) + return false; + + for (var i = 0; i < passNames.Length; i++) + { + if (string.Equals(passNames[i], passName, StringComparison.Ordinal)) + return true; + } + + return false; + } + + public static bool IsSubsetOf(string[] subset, string[] superset) + { + var set = new HashSet(superset ?? new string[0], StringComparer.Ordinal); + if (subset == null) + return true; + + for (var i = 0; i < subset.Length; i++) + { + if (!set.Contains(subset[i])) + return false; + } + + return true; + } + + public static bool AreKeywordSetsEqual(string[] a, string[] b) + { + var normalizedA = ToCatalogOrderedManagedKeywords(a); + var normalizedB = ToCatalogOrderedManagedKeywords(b); + if (normalizedA.Length != normalizedB.Length) + return false; + + for (var i = 0; i < normalizedA.Length; i++) + { + if (!string.Equals(normalizedA[i], normalizedB[i], StringComparison.Ordinal)) + return false; + } + + return true; + } + + private static HashSet GetDeclaredKeywords(string passName, PassType passType) + { + if (passType == PassType.ShadowCaster) + return DeclaredDepthShadowKeywords; + + if (string.Equals(passName, "DepthOnly", StringComparison.Ordinal)) + return DeclaredDepthShadowKeywords; + + if (string.Equals(passName, "NBCameraOpaqueDistortPass", StringComparison.Ordinal) || + string.Equals(passName, "NBDeferredDistortPass", StringComparison.Ordinal)) + { + return DeclaredDistortKeywords; + } + + if (string.Equals(passName, "Universal2D", StringComparison.Ordinal)) + return DeclaredUniversal2DKeywords; + + return DeclaredForwardKeywords; + } + + private static HashSet GetDeclaredShaderVariantKeywords(string passName, PassType passType) + { + if (passType == PassType.ShadowCaster) + return DeclaredShadowCasterShaderVariantKeywords; + + if (string.Equals(passName, "DepthOnly", StringComparison.Ordinal)) + return DeclaredDepthOnlyShaderVariantKeywords; + + if (string.Equals(passName, "NBCameraOpaqueDistortPass", StringComparison.Ordinal) || + string.Equals(passName, "NBDeferredDistortPass", StringComparison.Ordinal)) + { + return DeclaredDistortShaderVariantKeywords; + } + + if (string.Equals(passName, "Universal2D", StringComparison.Ordinal)) + return DeclaredUniversal2DShaderVariantKeywords; + + return DeclaredForwardShaderVariantKeywords; + } + + private static bool IsCatalogExternalShaderKeyword(string keyword) + { + return !string.IsNullOrEmpty(keyword) && CatalogExternalShaderKeywordSet.Contains(keyword); + } + + private static readonly string[] CatalogExternalShaderKeywordOrder = + { + "EVALUATE_SH_VERTEX", + "EVALUATE_SH_MIXED", + "SOFT_UI_FRAME", + "UNITY_UI_CLIP_RECT", + "_ADDITIONAL_LIGHTS_VERTEX", + "_ADDITIONAL_LIGHTS", + "_CASTING_PUNCTUAL_LIGHT_SHADOW" + }; + + private static readonly HashSet CatalogExternalShaderKeywordSet = + new HashSet(CatalogExternalShaderKeywordOrder, StringComparer.Ordinal); + + private static readonly HashSet DeclaredForwardKeywords = BuildDeclaredKeywordSet( + "NB_DEBUG_DISSOLVE", + "NB_DEBUG_DISTORT", + "NB_DEBUG_FRESNEL", + "NB_DEBUG_MASK", + "NB_DEBUG_PNOISE", + "NB_DEBUG_VERTEX_OFFSET", + "VFX_SIX_WAY_ABSORPTION", + "_ALPHAMODULATE_ON", + "_ALPHAPREMULTIPLY_ON", + "_ALPHATEST_ON", + "_CHROMATIC_ABERRATION", + "_COLORMAPBLEND", + "_COLOR_RAMP", + "_COLOR_RAMP_MAP", + "_DEPTH_DECAL", + "_DEPTH_OUTLINE", + "_DISSOLVE", + "_DISSOLVE_MASK", + "_DISSOLVE_RAMP", + "_DISSOLVE_RAMP_MAP", + "_DISTANCE_FADE", + "_DISTORT_REFRACTION", + "_EMISSION", + "_FLIPBOOKBLENDING_ON", + "_FRESNEL", + "_FX_LIGHT_MODE_BLINN_PHONG", + "_FX_LIGHT_MODE_HALF_LAMBERT", + "_FX_LIGHT_MODE_PBR", + "_FX_LIGHT_MODE_SIX_WAY", + "_FX_LIGHT_MODE_UNLIT", + "_HOUDINI_VAT_DYNAMIC_REMESH", + "_HOUDINI_VAT_PARTICLE_SPRITE", + "_HOUDINI_VAT_RIGIDBODY", + "_HOUDINI_VAT_SOFTBODY", + "_MASKMAP_ON", + "_MASKMAP2_ON", + "_MASKMAP3_ON", + "_MATCAP", + "_NOISEMAP", + "_NOISE_MASKMAP", + "_NORMALMAP", + "_OVERRIDE_Z", + "_PARALLAX_MAPPING", + "_PROGRAM_NOISE", + "_PROGRAM_NOISE_SIMPLE", + "_PROGRAM_NOISE_VORONOI", + "_SCRIPTABLETIME", + "_SHARED_UV", + "_SOFTPARTICLES_ON", + "_SPECULAR_COLOR", + "_STENCIL_WITHOUT_PLAYER", + "_TYFLOW_VAT_ABSOLUTE", + "_TYFLOW_VAT_RELATIVE", + "_TYFLOW_VAT_SKIN_PR", + "_TYFLOW_VAT_SKIN_PRSAVE", + "_TYFLOW_VAT_SKIN_PRSXYZ", + "_TYFLOW_VAT_SKIN_R", + "_UNSCALETIME", + "_VAT", + "_VAT_HOUDINI", + "_VAT_TYFLOW", + "_VERTEX_OFFSET", + "_VERTEX_OFFSET_MASKMAP"); + + private static readonly HashSet DeclaredDistortKeywords = BuildDeclaredKeywordSet( + "_ALPHAMODULATE_ON", + "_ALPHAPREMULTIPLY_ON", + "_ALPHATEST_ON", + "_CHROMATIC_ABERRATION", + "_DEPTH_DECAL", + "_DEPTH_OUTLINE", + "_DISSOLVE", + "_DISSOLVE_MASK", + "_DISSOLVE_RAMP", + "_DISSOLVE_RAMP_MAP", + "_DISTANCE_FADE", + "_DISTORT_REFRACTION", + "_FLIPBOOKBLENDING_ON", + "_FRESNEL", + "_FX_LIGHT_MODE_UNLIT", + "_MASKMAP_ON", + "_MASKMAP2_ON", + "_MASKMAP3_ON", + "_NOISEMAP", + "_NOISE_MASKMAP", + "_NORMALMAP", + "_PROGRAM_NOISE", + "_PROGRAM_NOISE_SIMPLE", + "_PROGRAM_NOISE_VORONOI", + "_SCRIPTABLETIME", + "_SHARED_UV", + "_SOFTPARTICLES_ON", + "_STENCIL_WITHOUT_PLAYER", + "_UNSCALETIME", + "_VERTEX_OFFSET", + "_VERTEX_OFFSET_MASKMAP"); + + private static readonly HashSet DeclaredDepthShadowKeywords = BuildDeclaredKeywordSet( + "_ALPHATEST_ON", + "_DISSOLVE", + "_DISSOLVE_MASK", + "_FLIPBOOKBLENDING_ON", + "_HOUDINI_VAT_DYNAMIC_REMESH", + "_HOUDINI_VAT_PARTICLE_SPRITE", + "_HOUDINI_VAT_RIGIDBODY", + "_HOUDINI_VAT_SOFTBODY", + "_MASKMAP_ON", + "_MASKMAP2_ON", + "_MASKMAP3_ON", + "_NOISEMAP", + "_NOISE_MASKMAP", + "_PROGRAM_NOISE", + "_PROGRAM_NOISE_SIMPLE", + "_PROGRAM_NOISE_VORONOI", + "_SCRIPTABLETIME", + "_SHARED_UV", + "_TYFLOW_VAT_ABSOLUTE", + "_TYFLOW_VAT_RELATIVE", + "_TYFLOW_VAT_SKIN_PR", + "_TYFLOW_VAT_SKIN_PRSAVE", + "_TYFLOW_VAT_SKIN_PRSXYZ", + "_TYFLOW_VAT_SKIN_R", + "_UNSCALETIME", + "_VAT", + "_VAT_HOUDINI", + "_VAT_TYFLOW", + "_VERTEX_OFFSET", + "_VERTEX_OFFSET_MASKMAP"); + + private static readonly HashSet DeclaredUniversal2DKeywords = BuildDeclaredKeywordSet( + "_ALPHAMODULATE_ON", + "_ALPHAPREMULTIPLY_ON", + "_ALPHATEST_ON", + "_CHROMATIC_ABERRATION", + "_COLORMAPBLEND", + "_COLOR_RAMP", + "_COLOR_RAMP_MAP", + "_DISSOLVE", + "_DISSOLVE_MASK", + "_DISSOLVE_RAMP", + "_DISSOLVE_RAMP_MAP", + "_EMISSION", + "_FLIPBOOKBLENDING_ON", + "_FRESNEL", + "_FX_LIGHT_MODE_UNLIT", + "_MASKMAP_ON", + "_MASKMAP2_ON", + "_MASKMAP3_ON", + "_NOISEMAP", + "_NOISE_MASKMAP", + "_NORMALMAP", + "_PARCUSTOMDATA_ON", + "_PROGRAM_NOISE", + "_PROGRAM_NOISE_SIMPLE", + "_PROGRAM_NOISE_VORONOI", + "_SCREEN_DISTORT_MODE", + "_SCRIPTABLETIME", + "_SHARED_UV", + "_STENCIL_WITHOUT_PLAYER", + "_UNSCALETIME", + "_VERTEX_OFFSET", + "_VERTEX_OFFSET_MASKMAP"); + + private static readonly HashSet DeclaredForwardShaderVariantKeywords = + BuildDeclaredShaderVariantKeywordSet( + DeclaredForwardKeywords, + "SOFT_UI_FRAME", + "EVALUATE_SH_MIXED", + "EVALUATE_SH_VERTEX", + "UNITY_UI_CLIP_RECT", + "_ADDITIONAL_LIGHTS_VERTEX", + "_ADDITIONAL_LIGHTS"); + + private static readonly HashSet DeclaredDistortShaderVariantKeywords = + BuildDeclaredShaderVariantKeywordSet( + DeclaredDistortKeywords, + "SOFT_UI_FRAME", + "EVALUATE_SH_MIXED", + "EVALUATE_SH_VERTEX"); + + private static readonly HashSet DeclaredDepthOnlyShaderVariantKeywords = + BuildDeclaredShaderVariantKeywordSet( + DeclaredDepthShadowKeywords); + + private static readonly HashSet DeclaredShadowCasterShaderVariantKeywords = + BuildDeclaredShaderVariantKeywordSet( + DeclaredDepthShadowKeywords, + "_CASTING_PUNCTUAL_LIGHT_SHADOW"); + + private static readonly HashSet DeclaredUniversal2DShaderVariantKeywords = + BuildDeclaredShaderVariantKeywordSet( + DeclaredUniversal2DKeywords, + "SOFT_UI_FRAME", + "EVALUATE_SH_MIXED", + "EVALUATE_SH_VERTEX", + "UNITY_UI_CLIP_RECT", + "_ADDITIONAL_LIGHTS_VERTEX", + "_ADDITIONAL_LIGHTS"); + + private static HashSet BuildDeclaredKeywordSet(params string[] keywords) + { + var result = new HashSet(StringComparer.Ordinal); + if (keywords == null) + return result; + + for (var i = 0; i < keywords.Length; i++) + { + var keyword = keywords[i]; + if (NBShaderFeatureCatalog.IsManagedKeyword(keyword)) + result.Add(keyword); + } + + return result; + } + + private static HashSet BuildDeclaredShaderVariantKeywordSet( + HashSet managedKeywords, + params string[] externalKeywords) + { + var result = new HashSet(managedKeywords ?? new HashSet(), StringComparer.Ordinal); + if (externalKeywords == null) + return result; + + for (var i = 0; i < externalKeywords.Length; i++) + { + var keyword = externalKeywords[i]; + if (IsCatalogExternalShaderKeyword(keyword)) + result.Add(keyword); + } + + return result; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildInfo.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildInfo.cs.meta new file mode 100644 index 00000000..0498c2f5 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48cf3e4ab2374d47bbb51283b80ad2d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildStripOverride.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildStripOverride.cs new file mode 100644 index 00000000..2c5d9238 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildStripOverride.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using NBShader; + +namespace NBShaders2.Editor.FeatureLevel +{ + public static class NBShaderFeatureLevelBuildStripOverride + { + private static readonly Stack s_OverrideStack = new Stack(); + + public static bool hasOverride { get { return s_OverrideStack.Count > 0; } } + + internal static bool TryGetCurrentTier(out NBShaderFeatureTier tier) + { + if (s_OverrideStack.Count > 0) + { + tier = s_OverrideStack.Peek(); + return true; + } + + tier = NBShaderFeatureTier.Ultra; + return false; + } + + public static IDisposable PushExplicitTier(NBShaderFeatureTier tier) + { + NBShaderVariantStripper.ResetMissingExplicitTierWarning(); + s_OverrideStack.Push(tier); + return new Scope(); + } + + private sealed class Scope : IDisposable + { + private bool m_Disposed; + + public void Dispose() + { + if (m_Disposed) + return; + m_Disposed = true; + if (s_OverrideStack.Count > 0) + s_OverrideStack.Pop(); + } + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildStripOverride.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildStripOverride.cs.meta new file mode 100644 index 00000000..350260fe --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelBuildStripOverride.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21bd03c909bfb4e9f97d2c9524827cce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelCatalog.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelCatalog.cs new file mode 100644 index 00000000..15ea7c71 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelCatalog.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using NBShader; + +namespace NBShaders2.Editor.FeatureLevel +{ + public static class NBShaderFeatureLevelCatalog + { + public const string ShaderName = NBShaderFeatureCatalog.ShaderName; + + public static string[] ManagedKeywords + { + get { return (string[])NBShaderFeatureCatalog.RawKeywords.Clone(); } + } + + public static string[] ManagedPassFeatures + { + get { return (string[])NBShaderPassFeatureCatalog.RawPassFeatureIds.Clone(); } + } + + public static bool IsManagedKeyword(string keyword) + { + return NBShaderFeatureCatalog.IsManagedKeyword(keyword); + } + + public static bool IsManagedPassFeature(string passFeatureId) + { + return NBShaderPassFeatureCatalog.IsManagedPassFeature(passFeatureId); + } + + public static bool TryGetManagedPassFeatureInfo( + string passFeatureId, + out string passName, + out string displayName) + { + NBShaderPassFeatureInfo feature; + if (NBShaderPassFeatureCatalog.TryGetPassFeature(passFeatureId, out feature)) + { + passName = feature.passName; + displayName = feature.displayName; + return true; + } + + passName = string.Empty; + displayName = string.Empty; + return false; + } + + public static bool TryGetManagedPassFeatureByPassName( + string passName, + out string passFeatureId) + { + NBShaderPassFeatureInfo feature; + if (NBShaderPassFeatureCatalog.TryGetPassFeatureByPassName(passName, out feature)) + { + passFeatureId = feature.id; + return true; + } + + passFeatureId = string.Empty; + return false; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelCatalog.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelCatalog.cs.meta new file mode 100644 index 00000000..a0906d58 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelCatalog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8da3dc0041f2c47a38e0d1c1c20dc493 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelEditorAPI.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelEditorAPI.cs new file mode 100644 index 00000000..588c2798 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelEditorAPI.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using NBShader; +using UnityEditor.Rendering; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NBShaders2.Editor.FeatureLevel +{ + /// + /// Public Editor API for CI/custom build scripts. Override scopes are process-local and never saved + /// into ProjectSettings/NBShaderFeatureLevels.asset. + /// + public static class NBShaderFeatureLevelEditorAPI + { + public static IDisposable OverrideBuildStripExplicitTier(NBShaderFeatureTier tier) + { + return NBShaderFeatureLevelBuildStripOverride.PushExplicitTier(tier); + } + + public static string DefaultGeneratedRuntimeSettingsAssetPath + { + get { return NBShaderRuntimeSettingsSynchronizer.DefaultGeneratedRuntimeSettingsAssetPath; } + } + + public static HashSet GetAllowedManagedKeywords(NBShaderFeatureTier tier) + { + return NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForBuildInfoNoSave(tier); + } + + public static HashSet GetAllowedManagedPassFeatures(NBShaderFeatureTier tier) + { + return NBShaderFeatureLevelProjectSettings.instance.GetAllowedPassFeatureSetForBuildInfoNoSave(tier); + } + + public static bool TryGetMaterialBuildInfo( + Material material, + NBShaderFeatureTier tier, + out NBShaderMaterialBuildInfo buildInfo, + NBShaderBuildInfoMode mode = NBShaderBuildInfoMode.ExactMaterialVariants) + { + buildInfo = null; + if (!NBShaderMaterialIntentResolver.IsNBShaderMaterial(material)) + return false; + + buildInfo = GetBuildInfo(material, tier, mode); + return buildInfo != null; + } + + public static NBShaderMaterialBuildInfo GetBuildInfo( + Material material, + NBShaderFeatureTier tier, + NBShaderBuildInfoMode mode = NBShaderBuildInfoMode.ExactMaterialVariants) + { + if (!NBShaderMaterialIntentResolver.IsNBShaderMaterial(material)) + return null; + + var allowedKeywords = NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForBuildInfoNoSave(tier); + var allowedPassFeatures = NBShaderFeatureLevelProjectSettings.instance.GetAllowedPassFeatureSetForBuildInfoNoSave(tier); + var intent = NBShaderMaterialIntentResolver.Resolve(material, tier, allowedKeywords, allowedPassFeatures); + return new NBShaderMaterialBuildInfo( + material, + tier, + mode, + NBShaderBuildInfoUtility.ToCatalogOrderedManagedKeywords(allowedKeywords), + intent.effectiveKeywords, + intent.strippedManagedKeywords, + BuildPassInfo(intent.passes), + NBShaderBuildInfoUtility.ToCatalogOrderedPassFeatures(allowedPassFeatures)); + } + + public static NBShaderBuildInfoSet GetBuildInfo( + NBShaderFeatureTier tier, + IEnumerable materials, + NBShaderBuildInfoMode mode = NBShaderBuildInfoMode.ExactMaterialVariants) + { + var result = new List(); + if (materials != null) + { + foreach (var material in materials) + { + NBShaderMaterialBuildInfo buildInfo; + if (TryGetMaterialBuildInfo(material, tier, out buildInfo, mode)) + result.Add(buildInfo); + } + } + + if (result.Count == 0) + return null; + + return new NBShaderBuildInfoSet( + tier, + mode, + result.ToArray(), + NBShaderBuildInfoUtility.ToCatalogOrderedManagedKeywords( + NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForBuildInfoNoSave(tier)), + NBShaderBuildInfoUtility.ToCatalogOrderedPassFeatures( + NBShaderFeatureLevelProjectSettings.instance.GetAllowedPassFeatureSetForBuildInfoNoSave(tier))); + } + + public static bool ShouldKeepVariant( + Shader shader, + ShaderSnippetData snippet, + ShaderCompilerData compilerData, + NBShaderMaterialBuildInfo buildInfo) + { + if (buildInfo == null) + return true; + + return ShouldKeepVariant( + shader, + snippet.passName, + snippet.passType, + ExtractManagedKeywords(shader, compilerData), + buildInfo); + } + + public static bool ShouldKeepVariant( + Shader shader, + ShaderSnippetData snippet, + ShaderCompilerData compilerData, + NBShaderBuildInfoSet buildInfo) + { + if (buildInfo == null) + return true; + + return ShouldKeepVariant( + shader, + snippet.passName, + snippet.passType, + ExtractManagedKeywords(shader, compilerData), + buildInfo); + } + + public static bool ShouldKeepVariant( + Shader shader, + string passName, + PassType passType, + IEnumerable keywords, + NBShaderMaterialBuildInfo buildInfo) + { + if (buildInfo == null) + return true; + + var set = new NBShaderBuildInfoSet( + buildInfo.tier, + buildInfo.mode, + new[] { buildInfo }, + buildInfo.allowedManagedKeywords, + buildInfo.allowedPassFeatures); + return ShouldKeepVariant(shader, passName, passType, keywords, set); + } + + public static bool ShouldKeepVariant( + Shader shader, + string passName, + PassType passType, + IEnumerable keywords, + NBShaderBuildInfoSet buildInfo) + { + if (shader == null || shader.name != NBShaderFeatureLevelCatalog.ShaderName || buildInfo == null) + return true; + + var managedKeywords = NBShaderBuildInfoUtility.ToCatalogOrderedManagedKeywords(keywords); + if (!buildInfo.hasMaterials) + return true; + + if (buildInfo.mode == NBShaderBuildInfoMode.TierAndPass) + return IsPassIncluded(passName, passType, buildInfo) && + NBShaderBuildInfoUtility.IsSubsetOf(managedKeywords, buildInfo.allowedManagedKeywords); + + var variants = buildInfo.variants; + var declaredCompilerKeywords = NBShaderBuildInfoUtility.FilterKeywordsForPass(passName, passType, managedKeywords); + for (var i = 0; i < variants.Length; i++) + { + var variant = variants[i]; + if (variant == null || !IsSameShader(shader, variant.shader)) + continue; + + if (!IsPassMatch(passName, passType, variant.passName, variant.passType)) + continue; + + if (NBShaderBuildInfoUtility.AreKeywordSetsEqual(declaredCompilerKeywords, variant.keywords)) + return true; + } + + return false; + } + + public static bool WriteRuntimeSettingsAsset(NBShaderFeatureRuntimeSettings asset) + { + return NBShaderRuntimeSettingsSynchronizer.WriteProjectSettingsToRuntimeAsset(asset); + } + + public static bool WriteRuntimeSettingsAssetNoSave(NBShaderFeatureRuntimeSettings asset) + { + return NBShaderRuntimeSettingsSynchronizer.WriteProjectSettingsSnapshotToRuntimeAssetNoSave(asset); + } + + public static NBShaderFeatureRuntimeSettings WriteDefaultRuntimeSettingsAsset(out string assetPath) + { + return NBShaderRuntimeSettingsSynchronizer.WriteDefaultGeneratedRuntimeSettingsAsset(out assetPath); + } + + public static NBShaderFeatureRuntimeSettings WriteRuntimeSettingsAssetOrDefault( + NBShaderFeatureRuntimeSettings explicitAsset, + out string assetPath) + { + return NBShaderRuntimeSettingsSynchronizer.WriteRuntimeSettingsAssetOrDefault(explicitAsset, out assetPath); + } + + private static NBShaderPassBuildInfo[] BuildPassInfo(NBShaderPassIntent[] passes) + { + if (passes == null || passes.Length == 0) + return new NBShaderPassBuildInfo[0]; + + var result = new NBShaderPassBuildInfo[passes.Length]; + for (var i = 0; i < passes.Length; i++) + { + var pass = passes[i]; + result[i] = new NBShaderPassBuildInfo( + pass.passName, + NBShaderBuildInfoUtility.GetPassType(pass.passName), + pass.enabledByMaterial, + pass.allowedByTier, + pass.included, + pass.reason); + } + + return result; + } + + private static string[] ExtractManagedKeywords(Shader shader, ShaderCompilerData compilerData) + { + if (shader == null) + return new string[0]; + + var result = new List(); + var keywords = compilerData.shaderKeywordSet.GetShaderKeywords(); + for (var i = 0; i < keywords.Length; i++) + { + var keywordName = keywords[i].name; + if (NBShaderFeatureLevelCatalog.IsManagedKeyword(keywordName)) + result.Add(keywordName); + } + + return NBShaderBuildInfoUtility.ToCatalogOrderedManagedKeywords(result); + } + + private static bool IsPassIncluded(string passName, PassType passType, NBShaderBuildInfoSet buildInfo) + { + if (buildInfo == null) + return true; + + if (!string.IsNullOrEmpty(passName)) + return NBShaderBuildInfoUtility.ContainsPassName(buildInfo.includedPassNames, passName); + + var variants = buildInfo.variants; + for (var i = 0; i < variants.Length; i++) + { + var variant = variants[i]; + if (variant != null && variant.passType == passType) + return true; + } + + return false; + } + + private static bool IsPassMatch(string passName, PassType passType, string targetPassName, PassType targetPassType) + { + if (!string.IsNullOrEmpty(passName) && !string.IsNullOrEmpty(targetPassName)) + return string.Equals(passName, targetPassName, StringComparison.Ordinal); + + return passType == targetPassType; + } + + private static bool IsSameShader(Shader a, Shader b) + { + if (a == null || b == null) + return false; + + return ReferenceEquals(a, b) || string.Equals(a.name, b.name, StringComparison.Ordinal); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelEditorAPI.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelEditorAPI.cs.meta new file mode 100644 index 00000000..8481e1a2 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelEditorAPI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 00d0583b58944e79978bb3deeaf7bdf7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelMaterialApplier.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelMaterialApplier.cs new file mode 100644 index 00000000..e087542c --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelMaterialApplier.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using NBShader; +using UnityEngine; + +namespace NBShaders2.Editor.FeatureLevel +{ + internal static class NBShaderFeatureLevelMaterialApplier + { + private const string FeatureTierPropertyName = "_NBShaderFeatureTier"; + + public static bool Apply(Material material, NBShaderFeatureTier tier, bool writeTierProperty, bool applyResolvedState) + { + bool changed; + return Apply(material, tier, writeTierProperty, applyResolvedState, out changed); + } + + public static bool Apply( + Material material, + NBShaderFeatureTier tier, + bool writeTierProperty, + bool applyResolvedState, + out bool changed) + { + changed = false; + if (!NBShaderMaterialIntentResolver.IsNBShaderMaterial(material)) + return false; + + if (writeTierProperty && + material.HasProperty(FeatureTierPropertyName) && + !Mathf.Approximately(material.GetFloat(FeatureTierPropertyName), (float)tier)) + { + material.SetFloat(FeatureTierPropertyName, (float)tier); + changed = true; + } + + if (!applyResolvedState) + return true; + + var allowedKeywords = NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForBuildInfoNoSave(tier); + var allowedPassFeatures = NBShaderFeatureLevelProjectSettings.instance.GetAllowedPassFeatureSetForBuildInfoNoSave(tier); + var result = NBShaderMaterialIntentResolver.Resolve(material, tier, allowedKeywords, allowedPassFeatures); + changed |= ApplyResolvedIntent(material, result); + return true; + } + + private static bool ApplyResolvedIntent(Material material, NBShaderMaterialIntentResult result) + { + if (material == null || result == null) + return false; + + var changed = false; + var effectiveKeywords = new HashSet(result.effectiveKeywords); + for (int i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++) + { + string keyword = NBShaderFeatureCatalog.RawKeywords[i]; + changed |= SetKeyword(material, keyword, effectiveKeywords.Contains(keyword)); + } + + changed |= SetKeyword(material, "EVALUATE_SH_VERTEX", effectiveKeywords.Contains("_FX_LIGHT_MODE_SIX_WAY")); + + for (int i = 0; i < result.passes.Length; i++) + { + NBShaderPassIntent pass = result.passes[i]; + if (!string.IsNullOrEmpty(pass.passName) && + material.GetShaderPassEnabled(pass.passName) != pass.included) + { + material.SetShaderPassEnabled(pass.passName, pass.included); + changed = true; + } + } + + return changed; + } + + private static bool SetKeyword(Material material, string keyword, bool enabled) + { + if (material == null || string.IsNullOrEmpty(keyword) || material.IsKeywordEnabled(keyword) == enabled) + return false; + + if (enabled) + material.EnableKeyword(keyword); + else + material.DisableKeyword(keyword); + + return true; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelMaterialApplier.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelMaterialApplier.cs.meta new file mode 100644 index 00000000..35dfbb36 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelMaterialApplier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f23b4e1c9a5465cbf64079ab0d81880 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelPreset.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelPreset.cs new file mode 100644 index 00000000..eb9fe9d4 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelPreset.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections.Generic; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor.FeatureLevel +{ + [CreateAssetMenu(fileName = "NBShaderDefaultFeatureLevels", menuName = "NBShader/Feature Level Preset")] + public sealed class NBShaderFeatureLevelPreset : ScriptableObject + { + [SerializeField] private NBShaderFeatureTierKeywordSet[] m_TierKeywordSets = new NBShaderFeatureTierKeywordSet[0]; + [SerializeField] private NBShaderFeatureTierPassSet[] m_TierPassSets = new NBShaderFeatureTierPassSet[0]; + + public NBShaderFeatureTierKeywordSet[] CreateTierKeywordSets() + { + var result = new NBShaderFeatureTierKeywordSet[4]; + for (var i = 0; i < result.Length; i++) + { + var tier = (NBShaderFeatureTier)i; + result[i] = new NBShaderFeatureTierKeywordSet + { + tier = tier, + allowedKeywords = GetAllowedKeywords(tier) + }; + } + + return result; + } + + public NBShaderFeatureTierPassSet[] CreateTierPassSets() + { + var result = new NBShaderFeatureTierPassSet[4]; + for (var i = 0; i < result.Length; i++) + { + var tier = (NBShaderFeatureTier)i; + result[i] = new NBShaderFeatureTierPassSet + { + tier = tier, + allowedPassFeatures = GetAllowedPassFeatures(tier) + }; + } + + return result; + } + + public string[] GetAllowedKeywords(NBShaderFeatureTier tier) + { + if (m_TierKeywordSets == null) + return new string[0]; + + for (var i = 0; i < m_TierKeywordSets.Length; i++) + { + var set = m_TierKeywordSets[i]; + if (set != null && set.tier == tier) + return SanitizeKeywords(set.allowedKeywords); + } + + return new string[0]; + } + + public string[] GetAllowedPassFeatures(NBShaderFeatureTier tier) + { + if (m_TierPassSets == null || m_TierPassSets.Length == 0) + return NBShaderPassFeatureCatalog.GetDefaultAllowedPassFeatures(tier); + + for (var i = 0; i < m_TierPassSets.Length; i++) + { + var set = m_TierPassSets[i]; + if (set != null && set.tier == tier) + return SanitizePassFeatures(set.allowedPassFeatures); + } + + return NBShaderPassFeatureCatalog.GetDefaultAllowedPassFeatures(tier); + } + + public void SetTierKeywordSets(NBShaderFeatureTierKeywordSet[] tierKeywordSets) + { + m_TierKeywordSets = new NBShaderFeatureTierKeywordSet[4]; + for (var i = 0; i < m_TierKeywordSets.Length; i++) + { + var tier = (NBShaderFeatureTier)i; + m_TierKeywordSets[i] = new NBShaderFeatureTierKeywordSet + { + tier = tier, + allowedKeywords = GetAllowedKeywords(tierKeywordSets, tier) + }; + } + } + + public void SetTierPassSets(NBShaderFeatureTierPassSet[] tierPassSets) + { + m_TierPassSets = new NBShaderFeatureTierPassSet[4]; + for (var i = 0; i < m_TierPassSets.Length; i++) + { + var tier = (NBShaderFeatureTier)i; + m_TierPassSets[i] = new NBShaderFeatureTierPassSet + { + tier = tier, + allowedPassFeatures = GetAllowedPassFeatures(tierPassSets, tier) + }; + } + } + + private static string[] SanitizeKeywords(string[] keywords) + { + if (keywords == null || keywords.Length == 0) + return new string[0]; + + var allowed = new HashSet(StringComparer.Ordinal); + for (var i = 0; i < keywords.Length; i++) + { + var keyword = keywords[i]; + if (NBShaderFeatureLevelCatalog.IsManagedKeyword(keyword)) + allowed.Add(keyword); + } + + var result = new List(); + var catalog = NBShaderFeatureLevelCatalog.ManagedKeywords; + for (var i = 0; i < catalog.Length; i++) + { + if (allowed.Contains(catalog[i])) + result.Add(catalog[i]); + } + + return result.ToArray(); + } + + private static string[] SanitizePassFeatures(string[] passFeatures) + { + if (passFeatures == null || passFeatures.Length == 0) + return new string[0]; + + var allowed = new HashSet(StringComparer.Ordinal); + for (var i = 0; i < passFeatures.Length; i++) + { + var passFeature = passFeatures[i]; + if (NBShaderFeatureLevelCatalog.IsManagedPassFeature(passFeature)) + allowed.Add(passFeature); + } + + var result = new List(); + var catalog = NBShaderFeatureLevelCatalog.ManagedPassFeatures; + for (var i = 0; i < catalog.Length; i++) + { + if (allowed.Contains(catalog[i])) + result.Add(catalog[i]); + } + + return result.ToArray(); + } + + private static string[] GetAllowedKeywords(NBShaderFeatureTierKeywordSet[] sets, NBShaderFeatureTier tier) + { + if (sets == null) + return new string[0]; + + for (var i = 0; i < sets.Length; i++) + { + var set = sets[i]; + if (set != null && set.tier == tier) + return SanitizeKeywords(set.allowedKeywords); + } + + return new string[0]; + } + + private static string[] GetAllowedPassFeatures(NBShaderFeatureTierPassSet[] sets, NBShaderFeatureTier tier) + { + if (sets == null || sets.Length == 0) + return NBShaderPassFeatureCatalog.GetDefaultAllowedPassFeatures(tier); + + for (var i = 0; i < sets.Length; i++) + { + var set = sets[i]; + if (set != null && set.tier == tier) + return SanitizePassFeatures(set.allowedPassFeatures); + } + + return NBShaderPassFeatureCatalog.GetDefaultAllowedPassFeatures(tier); + } + } + + internal static class NBShaderFeatureLevelPresetLoader + { + public const string DefaultPresetAssetPath = + "Packages/com.xuanxuan.nb.fx/NBShaders2/Editor/FeatureLevel/LevelAssets/NBShaderDefaultFeatureLevels.asset"; + + public static NBShaderFeatureTierKeywordSet[] LoadDefaultTierKeywordSets() + { + var preset = AssetDatabase.LoadAssetAtPath(DefaultPresetAssetPath); + if (preset != null) + return preset.CreateTierKeywordSets(); + + Debug.LogWarning( + "NBShader default feature level preset was not found at " + + DefaultPresetAssetPath + + ". Falling back to allowing all Catalog keywords for every tier."); + return CreateAllowAllTierKeywordSets(); + } + + public static NBShaderFeatureTierPassSet[] LoadDefaultTierPassSets() + { + var preset = AssetDatabase.LoadAssetAtPath(DefaultPresetAssetPath); + if (preset != null) + return preset.CreateTierPassSets(); + + return CreateAllowAllTierPassSets(); + } + + public static string[] LoadDefaultAllowedKeywords(NBShaderFeatureTier tier) + { + var sets = LoadDefaultTierKeywordSets(); + for (var i = 0; i < sets.Length; i++) + { + var set = sets[i]; + if (set != null && set.tier == tier) + return set.allowedKeywords ?? new string[0]; + } + + return new string[0]; + } + + public static string[] LoadDefaultAllowedPassFeatures(NBShaderFeatureTier tier) + { + var sets = LoadDefaultTierPassSets(); + for (var i = 0; i < sets.Length; i++) + { + var set = sets[i]; + if (set != null && set.tier == tier) + return set.allowedPassFeatures ?? new string[0]; + } + + return NBShaderPassFeatureCatalog.GetDefaultAllowedPassFeatures(tier); + } + + public static bool SaveDefaultTierKeywordSets(NBShaderFeatureTierKeywordSet[] tierKeywordSets) + { + return SaveDefaultFeatureSets(tierKeywordSets, null); + } + + public static bool SaveDefaultFeatureSets( + NBShaderFeatureTierKeywordSet[] tierKeywordSets, + NBShaderFeatureTierPassSet[] tierPassSets) + { + try + { + var preset = AssetDatabase.LoadAssetAtPath(DefaultPresetAssetPath); + if (preset == null) + { + preset = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(preset, DefaultPresetAssetPath); + } + + preset.SetTierKeywordSets(tierKeywordSets); + if (tierPassSets != null) + preset.SetTierPassSets(tierPassSets); + EditorUtility.SetDirty(preset); + AssetDatabase.SaveAssetIfDirty(preset); + AssetDatabase.ImportAsset(DefaultPresetAssetPath); + return AssetDatabase.LoadAssetAtPath(DefaultPresetAssetPath) != null; + } + catch (Exception exception) + { + Debug.LogError("Failed to save NBShader default feature level preset: " + exception); + return false; + } + } + + private static NBShaderFeatureTierKeywordSet[] CreateAllowAllTierKeywordSets() + { + var result = new NBShaderFeatureTierKeywordSet[4]; + for (var i = 0; i < result.Length; i++) + { + result[i] = new NBShaderFeatureTierKeywordSet + { + tier = (NBShaderFeatureTier)i, + allowedKeywords = (string[])NBShaderFeatureLevelCatalog.ManagedKeywords.Clone() + }; + } + + return result; + } + + private static NBShaderFeatureTierPassSet[] CreateAllowAllTierPassSets() + { + var result = new NBShaderFeatureTierPassSet[4]; + for (var i = 0; i < result.Length; i++) + { + var tier = (NBShaderFeatureTier)i; + result[i] = new NBShaderFeatureTierPassSet + { + tier = tier, + allowedPassFeatures = NBShaderPassFeatureCatalog.GetDefaultAllowedPassFeatures(tier) + }; + } + + return result; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelPreset.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelPreset.cs.meta new file mode 100644 index 00000000..e72a228f --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelPreset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a320954bde0b436381c4aef9f96ac237 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelProjectSettings.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelProjectSettings.cs new file mode 100644 index 00000000..23ab2bee --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelProjectSettings.cs @@ -0,0 +1,739 @@ +using System; +using System.Collections.Generic; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor.FeatureLevel +{ + [FilePath("ProjectSettings/NBShaderFeatureLevels.asset", FilePathAttribute.Location.ProjectFolder)] + public sealed class NBShaderFeatureLevelProjectSettings : ScriptableSingleton + { + private static readonly string[] DefaultQualityNames = { "Default" }; + + [SerializeField] private NBShaderFeatureTierKeywordSet[] m_TierKeywordSets; + [SerializeField] private NBShaderFeatureTierPassSet[] m_TierPassSets; + [SerializeField] private NBShaderQualityTierMapping[] m_QualityTierMappings; + [SerializeField] private bool m_EnableDebugSymbols; + + [NonSerialized] private bool m_Initialized; + [NonSerialized] private HashSet[] m_AllowedKeywordSetCache; + [NonSerialized] private bool m_AllowedKeywordSetCacheValid; + [NonSerialized] private HashSet[] m_AllowedPassFeatureSetCache; + [NonSerialized] private bool m_AllowedPassFeatureSetCacheValid; + + public NBShaderFeatureTierKeywordSet[] tierKeywordSets { get { EnsureInitialized(); InvalidateAllowedKeywordSetCache(); return m_TierKeywordSets; } } + public NBShaderFeatureTierPassSet[] tierPassSets { get { EnsureInitialized(); InvalidateAllowedPassFeatureSetCache(); return m_TierPassSets; } } + public NBShaderQualityTierMapping[] qualityTierMappings { get { EnsureInitialized(); return m_QualityTierMappings; } } + public bool enableDebugSymbols { get { return m_EnableDebugSymbols; } } + + public void EnsureInitialized() + { + if (m_Initialized && + HasValidTierKeywordSets() && + HasValidTierPassSets() && + HasValidQualityMappings() && + AreQualityMappingsCurrent()) + { + return; + } + + var changed = false; + if (m_TierKeywordSets == null || m_TierKeywordSets.Length != 4) + { + ResetTierKeywordSetsToDefault(); + changed = true; + } + else + { + changed |= NormalizeTierKeywordSets(); + } + + if (m_TierPassSets == null || m_TierPassSets.Length != 4) + { + ResetTierPassSetsToDefault(); + changed = true; + } + else + { + changed |= NormalizeTierPassSets(); + } + + if (m_QualityTierMappings == null || m_QualityTierMappings.Length == 0) + { + ResetQualityMappingsToDefault(); + changed = true; + } + else + { + changed |= NormalizeQualityMappingsWithCurrentQualityLevels(); + } + + if (changed) + { + Save(true); + } + + m_Initialized = true; + } + + public void ResetTierKeywordSetsToDefault() + { + m_TierKeywordSets = NBShaderFeatureLevelPresetLoader.LoadDefaultTierKeywordSets(); + InvalidateAllowedKeywordSetCache(); + } + + public void ResetTierPassSetsToDefault() + { + m_TierPassSets = NBShaderFeatureLevelPresetLoader.LoadDefaultTierPassSets(); + InvalidateAllowedPassFeatureSetCache(); + } + + public void ResetQualityMappingsToDefault() + { + var names = QualitySettings.names; + if (names == null || names.Length == 0) + names = DefaultQualityNames; + + m_QualityTierMappings = new NBShaderQualityTierMapping[names.Length]; + for (var i = 0; i < names.Length; i++) + { + m_QualityTierMappings[i] = new NBShaderQualityTierMapping + { + qualityName = names[i], + tier = GuessTierForQualityIndex(i, names.Length) + }; + } + } + + public HashSet GetAllowedKeywordSet(NBShaderFeatureTier tier) + { + return new HashSet(GetAllowedKeywordSetForReadOnlyUse(tier), StringComparer.Ordinal); + } + + public HashSet GetAllowedPassFeatureSet(NBShaderFeatureTier tier) + { + return new HashSet(GetAllowedPassFeatureSetForReadOnlyUse(tier), StringComparer.Ordinal); + } + + public bool IsKeywordAllowed(NBShaderFeatureTier tier, string keyword) + { + return GetAllowedKeywordSetForReadOnlyUse(tier).Contains(keyword); + } + + public bool IsPassFeatureAllowed(NBShaderFeatureTier tier, string passFeatureId) + { + return GetAllowedPassFeatureSetForReadOnlyUse(tier).Contains(passFeatureId); + } + + internal HashSet GetAllowedKeywordSetForReadOnlyUse(NBShaderFeatureTier tier) + { + EnsureInitialized(); + EnsureAllowedKeywordSetCache(); + return m_AllowedKeywordSetCache[ToTierIndex(tier)]; + } + + internal HashSet GetAllowedPassFeatureSetForReadOnlyUse(NBShaderFeatureTier tier) + { + EnsureInitialized(); + EnsureAllowedPassFeatureSetCache(); + return m_AllowedPassFeatureSetCache[ToTierIndex(tier)]; + } + + internal HashSet GetAllowedKeywordSetForBuildInfoNoSave(NBShaderFeatureTier tier) + { + var existing = FindTierKeywordSet(tier); + if (existing != null && existing.allowedKeywords != null) + return BuildSanitizedAllowedSet(existing.allowedKeywords); + + return BuildSanitizedAllowedSet(NBShaderFeatureLevelCatalog.ManagedKeywords); + } + + internal HashSet GetAllowedPassFeatureSetForBuildInfoNoSave(NBShaderFeatureTier tier) + { + var existing = FindTierPassSet(tier); + if (existing != null && existing.allowedPassFeatures != null) + return BuildSanitizedAllowedPassFeatureSet(existing.allowedPassFeatures); + + return BuildSanitizedAllowedPassFeatureSet(NBShaderFeatureLevelCatalog.ManagedPassFeatures); + } + + public void SetKeywordAllowed(NBShaderFeatureTier tier, string keyword, bool allowed) + { + EnsureInitialized(); + if (!NBShaderFeatureLevelCatalog.IsManagedKeyword(keyword)) + return; + + NBShaderFeatureTierKeywordSet target = null; + for (var i = 0; i < m_TierKeywordSets.Length; i++) + { + if (m_TierKeywordSets[i] != null && m_TierKeywordSets[i].tier == tier) + { + target = m_TierKeywordSets[i]; + break; + } + } + + if (target == null) + { + target = new NBShaderFeatureTierKeywordSet { tier = tier }; + var index = (int)tier; + if (index >= 0 && index < m_TierKeywordSets.Length) + m_TierKeywordSets[index] = target; + } + + var keywords = BuildSanitizedAllowedSet(target.allowedKeywords); + if (allowed) + keywords.Add(keyword); + else + keywords.Remove(keyword); + + target.allowedKeywords = ToCatalogOrderedArray(keywords); + InvalidateAllowedKeywordSetCache(); + } + + public void SetPassFeatureAllowed(NBShaderFeatureTier tier, string passFeatureId, bool allowed) + { + EnsureInitialized(); + if (!NBShaderFeatureLevelCatalog.IsManagedPassFeature(passFeatureId)) + return; + + NBShaderFeatureTierPassSet target = null; + for (var i = 0; i < m_TierPassSets.Length; i++) + { + if (m_TierPassSets[i] != null && m_TierPassSets[i].tier == tier) + { + target = m_TierPassSets[i]; + break; + } + } + + if (target == null) + { + target = new NBShaderFeatureTierPassSet { tier = tier }; + var index = (int)tier; + if (index >= 0 && index < m_TierPassSets.Length) + m_TierPassSets[index] = target; + } + + var passFeatures = BuildSanitizedAllowedPassFeatureSet(target.allowedPassFeatures); + if (allowed) + passFeatures.Add(passFeatureId); + else + passFeatures.Remove(passFeatureId); + + target.allowedPassFeatures = ToCatalogOrderedPassFeatureArray(passFeatures); + InvalidateAllowedPassFeatureSetCache(); + } + + public bool TryGetTierForQualityName(string qualityName, out NBShaderFeatureTier tier) + { + EnsureInitialized(); + tier = NBShaderFeatureTier.Ultra; + return TryGetTierForQualityNameNoSave(qualityName, out tier); + } + + internal bool TryGetTierForQualityNameNoSave(string qualityName, out NBShaderFeatureTier tier) + { + tier = NBShaderFeatureTier.Ultra; + if (string.IsNullOrEmpty(qualityName)) + return false; + + if (m_QualityTierMappings != null) + { + for (var i = 0; i < m_QualityTierMappings.Length; i++) + { + var mapping = m_QualityTierMappings[i]; + if (mapping == null || !string.Equals(mapping.qualityName, qualityName, StringComparison.Ordinal)) + continue; + + tier = mapping.tier; + return true; + } + } + + var names = QualitySettings.names; + if (names == null || names.Length == 0) + names = DefaultQualityNames; + + for (var i = 0; i < names.Length; i++) + { + if (!string.Equals(names[i], qualityName, StringComparison.Ordinal)) + continue; + + tier = GuessTierForQualityIndex(i, names.Length); + return true; + } + + return false; + } + + public string[] GetQualityNamesForTier(NBShaderFeatureTier tier) + { + EnsureInitialized(); + if (m_QualityTierMappings == null || m_QualityTierMappings.Length == 0) + return new string[0]; + + var names = new List(); + for (var i = 0; i < m_QualityTierMappings.Length; i++) + { + var mapping = m_QualityTierMappings[i]; + if (mapping != null && mapping.tier == tier && !string.IsNullOrEmpty(mapping.qualityName)) + names.Add(mapping.qualityName); + } + + return names.ToArray(); + } + + public void MoveQualityToTier(string qualityName, NBShaderFeatureTier tier) + { + EnsureInitialized(); + if (string.IsNullOrEmpty(qualityName)) + return; + + for (var i = 0; i < m_QualityTierMappings.Length; i++) + { + var mapping = m_QualityTierMappings[i]; + if (mapping == null || !string.Equals(mapping.qualityName, qualityName, StringComparison.Ordinal)) + continue; + + mapping.tier = tier; + return; + } + + var newMappings = new NBShaderQualityTierMapping[m_QualityTierMappings.Length + 1]; + Array.Copy(m_QualityTierMappings, newMappings, m_QualityTierMappings.Length); + newMappings[newMappings.Length - 1] = new NBShaderQualityTierMapping + { + qualityName = qualityName, + tier = tier + }; + m_QualityTierMappings = newMappings; + } + + public void SaveProjectSettings() + { + EnsureInitialized(); + Save(true); + } + + public void SetDebugSymbolsEnabled(bool enabled) + { + m_EnableDebugSymbols = enabled; + } + + public void SaveDebugSymbolsProjectSettings() + { + Save(true); + } + + private static NBShaderFeatureTier GuessTierForQualityIndex(int index, int count) + { + if (count <= 1) + return NBShaderFeatureTier.Ultra; + var normalized = index / (float)(count - 1); + if (normalized < 0.25f) return NBShaderFeatureTier.Low; + if (normalized < 0.50f) return NBShaderFeatureTier.Medium; + if (normalized < 0.75f) return NBShaderFeatureTier.High; + return NBShaderFeatureTier.Ultra; + } + + private bool NormalizeTierKeywordSets() + { + var changed = false; + NBShaderFeatureTierKeywordSet[] defaults = null; + var normalized = new NBShaderFeatureTierKeywordSet[4]; + for (var tierIndex = 0; tierIndex < normalized.Length; tierIndex++) + { + var tier = (NBShaderFeatureTier)tierIndex; + var existing = FindTierKeywordSet(tier); + if (existing == null) + { + if (defaults == null) + defaults = NBShaderFeatureLevelPresetLoader.LoadDefaultTierKeywordSets(); + changed = true; + } + + normalized[tierIndex] = new NBShaderFeatureTierKeywordSet + { + tier = tier, + allowedKeywords = existing != null + ? ToCatalogOrderedArray(BuildSanitizedAllowedSet(existing.allowedKeywords)) + : GetAllowedKeywords(defaults, tier) + }; + + if (existing != null && !AreKeywordArraysEquivalent(existing.allowedKeywords, normalized[tierIndex].allowedKeywords)) + changed = true; + } + + m_TierKeywordSets = normalized; + if (changed) + InvalidateAllowedKeywordSetCache(); + return changed; + } + + private bool NormalizeTierPassSets() + { + var changed = false; + NBShaderFeatureTierPassSet[] defaults = null; + var normalized = new NBShaderFeatureTierPassSet[4]; + for (var tierIndex = 0; tierIndex < normalized.Length; tierIndex++) + { + var tier = (NBShaderFeatureTier)tierIndex; + var existing = FindTierPassSet(tier); + if (existing == null) + { + if (defaults == null) + defaults = NBShaderFeatureLevelPresetLoader.LoadDefaultTierPassSets(); + changed = true; + } + + normalized[tierIndex] = new NBShaderFeatureTierPassSet + { + tier = tier, + allowedPassFeatures = existing != null + ? ToCatalogOrderedPassFeatureArray(BuildSanitizedAllowedPassFeatureSet(existing.allowedPassFeatures)) + : GetAllowedPassFeatures(defaults, tier) + }; + + if (existing != null && !ArePassFeatureArraysEquivalent(existing.allowedPassFeatures, normalized[tierIndex].allowedPassFeatures)) + changed = true; + } + + m_TierPassSets = normalized; + if (changed) + InvalidateAllowedPassFeatureSetCache(); + return changed; + } + + private bool HasValidTierKeywordSets() + { + if (m_TierKeywordSets == null || m_TierKeywordSets.Length != 4) + return false; + + for (var i = 0; i < m_TierKeywordSets.Length; i++) + { + var set = m_TierKeywordSets[i]; + if (set == null || set.tier != (NBShaderFeatureTier)i || set.allowedKeywords == null) + return false; + } + + return true; + } + + private bool HasValidTierPassSets() + { + if (m_TierPassSets == null || m_TierPassSets.Length != 4) + return false; + + for (var i = 0; i < m_TierPassSets.Length; i++) + { + var set = m_TierPassSets[i]; + if (set == null || set.tier != (NBShaderFeatureTier)i || set.allowedPassFeatures == null) + return false; + } + + return true; + } + + private bool HasValidQualityMappings() + { + return m_QualityTierMappings != null && m_QualityTierMappings.Length > 0; + } + + private bool AreQualityMappingsCurrent() + { + var names = QualitySettings.names; + if (names == null || names.Length == 0) + names = DefaultQualityNames; + + if (m_QualityTierMappings == null || m_QualityTierMappings.Length != names.Length) + return false; + + for (var i = 0; i < names.Length; i++) + { + var mapping = m_QualityTierMappings[i]; + if (mapping == null || !string.Equals(mapping.qualityName, names[i], StringComparison.Ordinal)) + return false; + } + + return true; + } + + private void EnsureAllowedKeywordSetCache() + { + if (m_AllowedKeywordSetCacheValid && + m_AllowedKeywordSetCache != null && + m_AllowedKeywordSetCache.Length == 4) + { + return; + } + + if (m_AllowedKeywordSetCache == null || m_AllowedKeywordSetCache.Length != 4) + m_AllowedKeywordSetCache = new HashSet[4]; + + for (var i = 0; i < m_AllowedKeywordSetCache.Length; i++) + m_AllowedKeywordSetCache[i] = BuildAllowedKeywordSet((NBShaderFeatureTier)i); + + m_AllowedKeywordSetCacheValid = true; + } + + private void EnsureAllowedPassFeatureSetCache() + { + if (m_AllowedPassFeatureSetCacheValid && + m_AllowedPassFeatureSetCache != null && + m_AllowedPassFeatureSetCache.Length == 4) + { + return; + } + + if (m_AllowedPassFeatureSetCache == null || m_AllowedPassFeatureSetCache.Length != 4) + m_AllowedPassFeatureSetCache = new HashSet[4]; + + for (var i = 0; i < m_AllowedPassFeatureSetCache.Length; i++) + m_AllowedPassFeatureSetCache[i] = BuildAllowedPassFeatureSet((NBShaderFeatureTier)i); + + m_AllowedPassFeatureSetCacheValid = true; + } + + private void InvalidateAllowedKeywordSetCache() + { + m_AllowedKeywordSetCacheValid = false; + } + + private void InvalidateAllowedPassFeatureSetCache() + { + m_AllowedPassFeatureSetCacheValid = false; + } + + private HashSet BuildAllowedKeywordSet(NBShaderFeatureTier tier) + { + var result = new HashSet(StringComparer.Ordinal); + if (m_TierKeywordSets == null) + return result; + + for (var i = 0; i < m_TierKeywordSets.Length; i++) + { + var set = m_TierKeywordSets[i]; + if (set == null || set.tier != tier || set.allowedKeywords == null) + continue; + + for (var k = 0; k < set.allowedKeywords.Length; k++) + { + var keyword = set.allowedKeywords[k]; + if (NBShaderFeatureLevelCatalog.IsManagedKeyword(keyword)) + result.Add(keyword); + } + } + + return result; + } + + private HashSet BuildAllowedPassFeatureSet(NBShaderFeatureTier tier) + { + var result = new HashSet(StringComparer.Ordinal); + if (m_TierPassSets == null) + return result; + + for (var i = 0; i < m_TierPassSets.Length; i++) + { + var set = m_TierPassSets[i]; + if (set == null || set.tier != tier || set.allowedPassFeatures == null) + continue; + + for (var k = 0; k < set.allowedPassFeatures.Length; k++) + { + var passFeature = set.allowedPassFeatures[k]; + if (NBShaderFeatureLevelCatalog.IsManagedPassFeature(passFeature)) + result.Add(passFeature); + } + } + + return result; + } + + private static int ToTierIndex(NBShaderFeatureTier tier) + { + var index = (int)tier; + return index >= 0 && index < 4 ? index : (int)NBShaderFeatureTier.Ultra; + } + + private NBShaderFeatureTierKeywordSet FindTierKeywordSet(NBShaderFeatureTier tier) + { + if (m_TierKeywordSets == null) + return null; + + for (var i = 0; i < m_TierKeywordSets.Length; i++) + { + var set = m_TierKeywordSets[i]; + if (set != null && set.tier == tier) + return set; + } + + return null; + } + + private NBShaderFeatureTierPassSet FindTierPassSet(NBShaderFeatureTier tier) + { + if (m_TierPassSets == null) + return null; + + for (var i = 0; i < m_TierPassSets.Length; i++) + { + var set = m_TierPassSets[i]; + if (set != null && set.tier == tier) + return set; + } + + return null; + } + + private bool NormalizeQualityMappingsWithCurrentQualityLevels() + { + var names = QualitySettings.names; + if (names == null || names.Length == 0) + names = DefaultQualityNames; + + var previous = new Dictionary(StringComparer.Ordinal); + if (m_QualityTierMappings != null) + { + for (var i = 0; i < m_QualityTierMappings.Length; i++) + { + var mapping = m_QualityTierMappings[i]; + if (mapping == null || string.IsNullOrEmpty(mapping.qualityName) || previous.ContainsKey(mapping.qualityName)) + continue; + + previous.Add(mapping.qualityName, mapping.tier); + } + } + + var changed = m_QualityTierMappings == null || m_QualityTierMappings.Length != names.Length; + m_QualityTierMappings = new NBShaderQualityTierMapping[names.Length]; + for (var i = 0; i < names.Length; i++) + { + NBShaderFeatureTier tier; + if (!previous.TryGetValue(names[i], out tier)) + { + tier = GuessTierForQualityIndex(i, names.Length); + changed = true; + } + + m_QualityTierMappings[i] = new NBShaderQualityTierMapping + { + qualityName = names[i], + tier = tier + }; + } + + return changed; + } + + private static HashSet BuildSanitizedAllowedSet(string[] keywords) + { + var result = new HashSet(StringComparer.Ordinal); + if (keywords == null) + return result; + + for (var i = 0; i < keywords.Length; i++) + { + var keyword = keywords[i]; + if (NBShaderFeatureLevelCatalog.IsManagedKeyword(keyword)) + result.Add(keyword); + } + + return result; + } + + private static HashSet BuildSanitizedAllowedPassFeatureSet(string[] passFeatures) + { + var result = new HashSet(StringComparer.Ordinal); + if (passFeatures == null) + return result; + + for (var i = 0; i < passFeatures.Length; i++) + { + var passFeature = passFeatures[i]; + if (NBShaderFeatureLevelCatalog.IsManagedPassFeature(passFeature)) + result.Add(passFeature); + } + + return result; + } + + private static string[] ToCatalogOrderedArray(HashSet keywords) + { + if (keywords == null || keywords.Count == 0) + return new string[0]; + + var result = new List(); + var catalog = NBShaderFeatureLevelCatalog.ManagedKeywords; + for (var i = 0; i < catalog.Length; i++) + { + if (keywords.Contains(catalog[i])) + result.Add(catalog[i]); + } + + return result.ToArray(); + } + + private static string[] ToCatalogOrderedPassFeatureArray(HashSet passFeatures) + { + if (passFeatures == null || passFeatures.Count == 0) + return new string[0]; + + var result = new List(); + var catalog = NBShaderFeatureLevelCatalog.ManagedPassFeatures; + for (var i = 0; i < catalog.Length; i++) + { + if (passFeatures.Contains(catalog[i])) + result.Add(catalog[i]); + } + + return result.ToArray(); + } + + private static string[] GetAllowedKeywords(NBShaderFeatureTierKeywordSet[] sets, NBShaderFeatureTier tier) + { + if (sets == null) + return new string[0]; + + for (var i = 0; i < sets.Length; i++) + { + var set = sets[i]; + if (set != null && set.tier == tier) + return set.allowedKeywords ?? new string[0]; + } + + return new string[0]; + } + + private static string[] GetAllowedPassFeatures(NBShaderFeatureTierPassSet[] sets, NBShaderFeatureTier tier) + { + if (sets == null) + return new string[0]; + + for (var i = 0; i < sets.Length; i++) + { + var set = sets[i]; + if (set != null && set.tier == tier) + return set.allowedPassFeatures ?? new string[0]; + } + + return new string[0]; + } + + private static bool AreKeywordArraysEquivalent(string[] a, string[] b) + { + var setA = BuildSanitizedAllowedSet(a); + var setB = BuildSanitizedAllowedSet(b); + return setA.SetEquals(setB); + } + + private static bool ArePassFeatureArraysEquivalent(string[] a, string[] b) + { + var setA = BuildSanitizedAllowedPassFeatureSet(a); + var setB = BuildSanitizedAllowedPassFeatureSet(b); + return setA.SetEquals(setB); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelProjectSettings.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelProjectSettings.cs.meta new file mode 100644 index 00000000..d4debcba --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelProjectSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ac3a7eef1342b4895b4c1a6bf2669486 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelRowCatalog.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelRowCatalog.cs new file mode 100644 index 00000000..f7d3e0f4 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelRowCatalog.cs @@ -0,0 +1,247 @@ +using System.Collections.Generic; +using NBShader; + +namespace NBShaders2.Editor.FeatureLevel +{ + internal enum NBShaderFeatureLevelRowKind + { + Group, + Keyword, + Pass + } + + internal enum NBShaderFeaturePerformanceCost + { + Low, + Medium, + High, + Ultra + } + + internal sealed class NBShaderFeatureLevelRow + { + public readonly NBShaderFeatureLevelRowKind kind; + public readonly string key; + public readonly string parentKey; + public readonly string keyword; + public readonly string passFeatureId; + public readonly string labelFallback; + public readonly NBShaderFeaturePerformanceCost performanceCost; + public readonly string effectFallback; + public readonly int depth; + + public NBShaderFeatureLevelRow( + NBShaderFeatureLevelRowKind kind, + string key, + string parentKey, + string keyword, + string passFeatureId, + string labelFallback, + NBShaderFeaturePerformanceCost performanceCost, + string effectFallback, + int depth) + { + this.kind = kind; + this.key = key; + this.parentKey = parentKey; + this.keyword = keyword; + this.passFeatureId = passFeatureId; + this.labelFallback = labelFallback; + this.performanceCost = performanceCost; + this.effectFallback = effectFallback; + this.depth = depth; + } + + public bool isKeyword + { + get { return kind == NBShaderFeatureLevelRowKind.Keyword; } + } + + public bool isPass + { + get { return kind == NBShaderFeatureLevelRowKind.Pass; } + } + } + + internal static class NBShaderFeatureLevelRowCatalog + { + public static readonly NBShaderFeatureLevelRow[] Rows = + { + Group("mode", null, "Mode", 0), + Group("transparent", "mode", "Transparent Mode", 1), + Keyword("_ALPHATEST_ON", "transparent", "Alpha Test", 2, NBShaderFeaturePerformanceCost.Medium, "Cuts pixels by alpha threshold."), + Keyword("_ALPHAPREMULTIPLY_ON", "transparent", "Premultiply Alpha", 2, NBShaderFeaturePerformanceCost.Low, "Uses premultiplied alpha blending."), + Keyword("_ALPHAMODULATE_ON", "transparent", "Alpha Modulate", 2, NBShaderFeaturePerformanceCost.Low, "Uses alpha modulation transparent blending."), + Group("time", "mode", "Time Mode", 1), + Keyword("_UNSCALETIME", "time", "Unscaled Time", 2, NBShaderFeaturePerformanceCost.Low, "Uses unscaled time."), + Keyword("_SCRIPTABLETIME", "time", "Scriptable Time", 2, NBShaderFeaturePerformanceCost.Low, "Uses script provided time value."), + + Group("base", null, "Base", 0), + Keyword("_DISTANCE_FADE", "base", "Distance Fade", 1, NBShaderFeaturePerformanceCost.Low, "Fades material by camera distance."), + Keyword("_SOFTPARTICLES_ON", "base", "Soft Particles", 1, NBShaderFeaturePerformanceCost.High, "Softens particles using scene depth."), + Keyword("_STENCIL_WITHOUT_PLAYER", "base", "Stencil Without Player", 1, NBShaderFeaturePerformanceCost.Low, "Uses stencil without player mask."), + Group("particle", "base", "Particle Data", 1), + Keyword("_PARCUSTOMDATA_ON", "particle", "Particle Custom Data", 2, NBShaderFeaturePerformanceCost.Low, "Reads particle custom data channels."), + + Group("light", null, "Lighting", 0), + Group("lightMode", "light", "Light Mode", 1), + Keyword("_FX_LIGHT_MODE_UNLIT", "lightMode", "Unlit Lighting", 2, NBShaderFeaturePerformanceCost.Low, "Uses unlit shading."), + Keyword("_FX_LIGHT_MODE_BLINN_PHONG", "lightMode", "Blinn-Phong Lighting", 2, NBShaderFeaturePerformanceCost.Medium, "Uses Blinn Phong lighting."), + Keyword("_FX_LIGHT_MODE_HALF_LAMBERT", "lightMode", "Half Lambert Lighting", 2, NBShaderFeaturePerformanceCost.Medium, "Uses half Lambert lighting."), + Keyword("_FX_LIGHT_MODE_PBR", "lightMode", "PBR Lighting", 2, NBShaderFeaturePerformanceCost.High, "Uses PBR lighting calculations."), + Keyword("_FX_LIGHT_MODE_SIX_WAY", "lightMode", "Six Way Lighting", 2, NBShaderFeaturePerformanceCost.Ultra, "Uses six way lighting data."), + Keyword("_SPECULAR_COLOR", "light", "Specular Color", 1, NBShaderFeaturePerformanceCost.Medium, "Adds specular color highlight."), + Keyword("_NORMALMAP", "light", "Normal Map", 1, NBShaderFeaturePerformanceCost.High, "Uses normal map lighting detail."), + Keyword("_MATCAP", "light", "MatCap", 1, NBShaderFeaturePerformanceCost.Medium, "Adds matcap lighting texture."), + Keyword("VFX_SIX_WAY_ABSORPTION", "light", "Six Way Absorption", 1, NBShaderFeaturePerformanceCost.High, "Adds absorption response for six way lighting."), + + Group("feature", null, "Feature", 0), + Keyword("_MASKMAP_ON", "feature", "Mask Map", 1, NBShaderFeaturePerformanceCost.Medium, "Uses the first mask map."), + Keyword("_MASKMAP2_ON", "_MASKMAP_ON", "Mask Map 2", 2, NBShaderFeaturePerformanceCost.Medium, "Uses the second mask map."), + Keyword("_MASKMAP3_ON", "_MASKMAP_ON", "Mask Map 3", 2, NBShaderFeaturePerformanceCost.Medium, "Uses the third mask map."), + Keyword("NB_DEBUG_MASK", "_MASKMAP_ON", "Debug Mask", 2, NBShaderFeaturePerformanceCost.Low, "Shows mask values for debugging."), + Keyword("_NOISEMAP", "feature", "Noise Map", 1, NBShaderFeaturePerformanceCost.High, "Uses a noise map for distortion."), + Keyword("_NOISE_MASKMAP", "_NOISEMAP", "Noise Mask Map", 2, NBShaderFeaturePerformanceCost.Medium, "Masks the distortion effect."), + Keyword("NB_DEBUG_DISTORT", "_NOISEMAP", "Debug Distort", 2, NBShaderFeaturePerformanceCost.Low, "Shows distortion strength for debugging."), + Keyword("_SCREEN_DISTORT_MODE", "_NOISEMAP", "Screen Distort", 2, NBShaderFeaturePerformanceCost.Ultra, "Samples screen texture for distortion."), + Keyword("_DISTORT_REFRACTION", "_NOISEMAP", "Distort Refraction", 2, NBShaderFeaturePerformanceCost.High, "Uses refraction style distortion."), + Keyword("_CHROMATIC_ABERRATION", "feature", "Chromatic Aberration", 1, NBShaderFeaturePerformanceCost.High, "Splits color channels for distortion fringe."), + Keyword("_EMISSION", "feature", "Emission", 1, NBShaderFeaturePerformanceCost.Medium, "Adds emissive color or texture contribution."), + Keyword("_COLORMAPBLEND", "feature", "Color Map Blend", 1, NBShaderFeaturePerformanceCost.Medium, "Blends an extra color gradient texture."), + Keyword("_COLOR_RAMP", "feature", "Color Ramp", 1, NBShaderFeaturePerformanceCost.Medium, "Remaps color through a ramp."), + Keyword("_COLOR_RAMP_MAP", "_COLOR_RAMP", "Color Ramp Map", 2, NBShaderFeaturePerformanceCost.Medium, "Uses a texture as the color ramp source."), + Keyword("_DISSOLVE", "feature", "Dissolve", 1, NBShaderFeaturePerformanceCost.High, "Clips and blends pixels for dissolve."), + Keyword("_DISSOLVE_MASK", "_DISSOLVE", "Dissolve Mask", 2, NBShaderFeaturePerformanceCost.High, "Uses a process mask for dissolve."), + Keyword("_DISSOLVE_RAMP", "_DISSOLVE", "Dissolve Ramp", 2, NBShaderFeaturePerformanceCost.Medium, "Adds ramp coloring to dissolve edges."), + Keyword("_DISSOLVE_RAMP_MAP", "_DISSOLVE_RAMP", "Dissolve Ramp Map", 3, NBShaderFeaturePerformanceCost.Medium, "Uses a texture for dissolve ramp color."), + Keyword("NB_DEBUG_DISSOLVE", "_DISSOLVE", "Debug Dissolve", 2, NBShaderFeaturePerformanceCost.Low, "Shows dissolve values for debugging."), + Keyword("_PROGRAM_NOISE", "feature", "Program Noise", 1, NBShaderFeaturePerformanceCost.High, "Generates procedural noise in shader."), + Keyword("_PROGRAM_NOISE_SIMPLE", "_PROGRAM_NOISE", "Program Noise Simple", 2, NBShaderFeaturePerformanceCost.High, "Enables simple procedural noise."), + Keyword("_PROGRAM_NOISE_VORONOI", "_PROGRAM_NOISE", "Program Noise Voronoi", 2, NBShaderFeaturePerformanceCost.High, "Enables Voronoi procedural noise."), + Keyword("NB_DEBUG_PNOISE", "_PROGRAM_NOISE", "Debug Program Noise", 2, NBShaderFeaturePerformanceCost.Low, "Shows procedural noise values for debugging."), + Keyword("_SHARED_UV", "feature", "Shared UV", 1, NBShaderFeaturePerformanceCost.Low, "Shares a common UV transform."), + Keyword("_FRESNEL", "feature", "Fresnel", 1, NBShaderFeaturePerformanceCost.Medium, "Adds view angle based rim lighting."), + Keyword("NB_DEBUG_FRESNEL", "_FRESNEL", "Debug Fresnel", 2, NBShaderFeaturePerformanceCost.Low, "Shows fresnel values for debugging."), + Keyword("_VERTEX_OFFSET", "feature", "Vertex Offset", 1, NBShaderFeaturePerformanceCost.High, "Offsets vertices in the shader."), + Keyword("_VERTEX_OFFSET_MASKMAP", "_VERTEX_OFFSET", "Vertex Offset Mask Map", 2, NBShaderFeaturePerformanceCost.High, "Masks vertex offset by texture."), + Keyword("NB_DEBUG_VERTEX_OFFSET", "_VERTEX_OFFSET", "Debug Vertex Offset", 2, NBShaderFeaturePerformanceCost.Low, "Shows vertex offset values for debugging."), + Group("depth", "feature", "Depth", 1), + Keyword("_DEPTH_DECAL", "depth", "Depth Decal", 2, NBShaderFeaturePerformanceCost.High, "Projects decal effect using scene depth."), + Keyword("_DEPTH_OUTLINE", "depth", "Depth Outline", 2, NBShaderFeaturePerformanceCost.High, "Creates outline effect using depth difference."), + Keyword("_OVERRIDE_Z", "depth", "Override Z", 2, NBShaderFeaturePerformanceCost.Medium, "Writes a fixed camera eye depth through SV_Depth."), + Keyword("_PARALLAX_MAPPING", "feature", "Parallax Mapping", 1, NBShaderFeaturePerformanceCost.High, "Offsets UVs for parallax depth."), + Keyword("_FLIPBOOKBLENDING_ON", "feature", "Flipbook Blending", 1, NBShaderFeaturePerformanceCost.Medium, "Blends between flipbook frames."), + Keyword("_VAT", "feature", "VAT", 1, NBShaderFeaturePerformanceCost.Ultra, "Enables vertex animation texture playback."), + Group("vatMode", "_VAT", "VAT Mode", 2), + Keyword("_VAT_HOUDINI", "vatMode", "Houdini VAT", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses Houdini VAT data layout."), + Keyword("_VAT_TYFLOW", "vatMode", "TyFlow VAT", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses TyFlow VAT data layout."), + Group("houdiniVat", "_VAT", "Houdini VAT", 2), + Keyword("_HOUDINI_VAT_SOFTBODY", "houdiniVat", "Houdini VAT Soft Body", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses Houdini soft body VAT mode."), + Keyword("_HOUDINI_VAT_RIGIDBODY", "houdiniVat", "Houdini VAT Rigid Body", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses Houdini rigid body VAT mode."), + Keyword("_HOUDINI_VAT_DYNAMIC_REMESH", "houdiniVat", "Houdini VAT Dynamic Remesh", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses Houdini dynamic remesh VAT mode."), + Keyword("_HOUDINI_VAT_PARTICLE_SPRITE", "houdiniVat", "Houdini VAT Particle Sprite", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses Houdini particle sprite VAT mode."), + Group("tyflowVat", "_VAT", "TyFlow VAT", 2), + Keyword("_TYFLOW_VAT_ABSOLUTE", "tyflowVat", "TyFlow VAT Absolute", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses TyFlow absolute VAT mode."), + Keyword("_TYFLOW_VAT_RELATIVE", "tyflowVat", "TyFlow VAT Relative", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses TyFlow relative VAT mode."), + Keyword("_TYFLOW_VAT_SKIN_R", "tyflowVat", "TyFlow VAT Skin R", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses TyFlow skin R VAT mode."), + Keyword("_TYFLOW_VAT_SKIN_PR", "tyflowVat", "TyFlow VAT Skin PR", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses TyFlow skin PR VAT mode."), + Keyword("_TYFLOW_VAT_SKIN_PRSAVE", "tyflowVat", "TyFlow VAT Skin PR Save", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses TyFlow skin PR save VAT mode."), + Keyword("_TYFLOW_VAT_SKIN_PRSXYZ", "tyflowVat", "TyFlow VAT Skin PRSXYZ", 3, NBShaderFeaturePerformanceCost.Ultra, "Uses TyFlow skin PRSXYZ VAT mode."), + + Group("passes", null, "Passes", 0), + Pass(NBShaderPassFeatureCatalog.BackFirstPassId, "passes", "Back First Pass", 1, NBShaderFeaturePerformanceCost.Medium, "Renders the optional back-face pre-pass."), + Pass(NBShaderPassFeatureCatalog.CameraOpaqueDistortPassId, "passes", "Camera Opaque Distort Pass", 1, NBShaderFeaturePerformanceCost.Ultra, "Renders the camera opaque texture screen distort pass."), + Pass(NBShaderPassFeatureCatalog.DeferredDistortPassId, "passes", "Deferred Distort Pass", 1, NBShaderFeaturePerformanceCost.Ultra, "Renders the deferred screen distort pass."), + Pass(NBShaderPassFeatureCatalog.DepthOnlyPassId, "passes", "Depth Only Pass", 1, NBShaderFeaturePerformanceCost.Medium, "Writes material depth for URP depth prepass usage."), + Pass(NBShaderPassFeatureCatalog.ShadowCasterPassId, "passes", "Shadow Caster Pass", 1, NBShaderFeaturePerformanceCost.High, "Renders the material into shadow maps."), + Pass(NBShaderPassFeatureCatalog.Universal2DPassId, "passes", "Universal 2D Pass", 1, NBShaderFeaturePerformanceCost.Medium, "Allows the material to render through URP 2D renderer.") + }; + + private static readonly HashSet ParentKeys = BuildParentKeys(); + private static readonly Dictionary RowsByKey = BuildRowsByKey(); + + public static bool HasChildren(NBShaderFeatureLevelRow row) + { + return row != null && ParentKeys.Contains(row.key); + } + + public static bool TryGetRow(string key, out NBShaderFeatureLevelRow row) + { + return RowsByKey.TryGetValue(key, out row); + } + + private static NBShaderFeatureLevelRow Group(string key, string parentKey, string labelFallback, int depth) + { + return new NBShaderFeatureLevelRow( + NBShaderFeatureLevelRowKind.Group, + key, + parentKey, + null, + null, + labelFallback, + NBShaderFeaturePerformanceCost.Low, + null, + depth); + } + + private static NBShaderFeatureLevelRow Keyword( + string keyword, + string parentKey, + string labelFallback, + int depth, + NBShaderFeaturePerformanceCost performanceCost, + string effectFallback) + { + return new NBShaderFeatureLevelRow( + NBShaderFeatureLevelRowKind.Keyword, + keyword, + parentKey, + keyword, + null, + labelFallback, + performanceCost, + effectFallback, + depth); + } + + private static NBShaderFeatureLevelRow Pass( + string passFeatureId, + string parentKey, + string labelFallback, + int depth, + NBShaderFeaturePerformanceCost performanceCost, + string effectFallback) + { + return new NBShaderFeatureLevelRow( + NBShaderFeatureLevelRowKind.Pass, + passFeatureId, + parentKey, + null, + passFeatureId, + labelFallback, + performanceCost, + effectFallback, + depth); + } + + private static HashSet BuildParentKeys() + { + var result = new HashSet(); + for (var i = 0; i < Rows.Length; i++) + { + if (!string.IsNullOrEmpty(Rows[i].parentKey)) + result.Add(Rows[i].parentKey); + } + + return result; + } + + private static Dictionary BuildRowsByKey() + { + var result = new Dictionary(); + for (var i = 0; i < Rows.Length; i++) + result[Rows[i].key] = Rows[i]; + return result; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelRowCatalog.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelRowCatalog.cs.meta new file mode 100644 index 00000000..c302d8af --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelRowCatalog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2abec81852044be281de893c9ef6ea3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelSettingsProvider.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelSettingsProvider.cs new file mode 100644 index 00000000..79096353 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelSettingsProvider.cs @@ -0,0 +1,881 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NBShader; +using NBShaderEditor; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor.FeatureLevel +{ + [InitializeOnLoad] + public static class NBShaderFeatureLevelSettingsProvider + { + internal const string SettingsPath = NBFXProjectSettings.SettingsPath; + private const float FeatureColumnWidth = 240f; + private const float TierColumnWidth = 92f; + private const float CostColumnWidth = 84f; + private const float EffectColumnWidth = 280f; + private const float DescriptionColumnWidth = 230f; + private const float RowHeight = 22f; + private const float HeaderHeight = 24f; + private const float TableMinHeight = 360f; + private const float TableMaxHeight = 640f; + private const float TableWidth = FeatureColumnWidth + TierColumnWidth * 4f + CostColumnWidth + EffectColumnWidth + DescriptionColumnWidth; + private const float RowIndentWidth = 14f; + private const string FoldoutSessionPrefix = "NBShaderFeatureLevelSettingsProvider.Foldout."; + + private sealed class RowContentCache + { + public GUIContent rowContent; + public GUIContent effectContent; + public GUIContent descriptionContent; + } + + private static readonly NBShaderFeatureTier[] Tiers = + { + NBShaderFeatureTier.Low, + NBShaderFeatureTier.Medium, + NBShaderFeatureTier.High, + NBShaderFeatureTier.Ultra + }; + + private static readonly Dictionary s_RowContentCache = + new Dictionary(StringComparer.Ordinal); + private static readonly Dictionary s_CostContentCache = + new Dictionary(); + private static readonly GUIContent[] s_QualitySummaryContents = new GUIContent[Tiers.Length]; + private static readonly string[] s_QualitySummaryTexts = new string[Tiers.Length]; + private static readonly StringBuilder s_QualitySummaryBuilder = new StringBuilder(128); + + private static Vector2 s_TableScrollPosition; + private static string s_ContentCacheLanguage; + private static GUIContent s_ProviderLabelContent; + private static GUIContent s_QualityDescriptionContent; + private static GUIContent s_NoValueContent; + private static string s_QualityMenuTipText; + private static int s_QualitySummaryHash; + + static NBShaderFeatureLevelSettingsProvider() + { + NBFXProjectSettings.RegisterSettingsSection( + "NBShaderFeatureLevels", + GetProviderLabelContent, + OnGUI, + new[] + { + "NBShader", + "Feature", + "Tier", + "Strip", + "Keyword", + "Quality", + "Apply", + "Material", + "Loaded Materials", + "Project Materials", + "应用", + "材质", + "等级", + "分级", + "剔除" + }, + 100); + } + + private static void OnGUI(string searchContext) + { + EnsureContentCacheForCurrentLanguage(); + + var settings = NBShaderFeatureLevelProjectSettings.instance; + settings.EnsureInitialized(); + + var changed = false; + + EditorGUILayout.HelpBox( + Text( + "featureLevel.help.message", + "Configure NBShader managed Catalog keywords and shader passes per tier, and bind Unity Quality levels. Build scripts select the build stripping tier through NBShaderFeatureLevelEditorAPI.OverrideBuildStripExplicitTier. Runtime settings assets can be updated from their own Inspector or Editor API. Catalog-external features are ignored."), + MessageType.Info); + + changed |= DrawFeatureLevelTable(settings); + + EditorGUILayout.Space(); + changed |= DrawButtons(settings); + + if (changed) + settings.SaveProjectSettings(); + } + + private static bool DrawFeatureLevelTable(NBShaderFeatureLevelProjectSettings settings) + { + var changed = false; + + EditorGUILayout.LabelField( + Text("featureLevel.table.title", "Feature Level Matrix"), + EditorStyles.boldLabel); + + s_TableScrollPosition = EditorGUILayout.BeginScrollView( + s_TableScrollPosition, + true, + true, + GUILayout.MinHeight(TableMinHeight), + GUILayout.MaxHeight(TableMaxHeight)); + + using (new GUILayout.VerticalScope(GUILayout.Width(TableWidth))) + { + DrawTableHeader(); + DrawQualityBindingRow(settings); + DrawTableSeparator(); + changed |= DrawFeatureRows(settings); + } + + EditorGUILayout.EndScrollView(); + + return changed; + } + + private static void DrawTableHeader() + { + using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar, GUILayout.Height(HeaderHeight))) + { + DrawHeaderCell( + Content( + "featureLevel.column.feature", + "Config / Feature", + "Tier settings and managed Catalog features."), + FeatureColumnWidth); + + for (var i = 0; i < Tiers.Length; i++) + DrawHeaderCell(GetTierContent(Tiers[i]), TierColumnWidth); + + DrawHeaderCell( + Content( + "featureLevel.column.cost", + "Performance Cost", + "Estimated shader cost when this feature is enabled."), + CostColumnWidth); + + DrawHeaderCell( + Content( + "featureLevel.column.effect", + "Feature Effect", + "Short description of what this keyword enables."), + EffectColumnWidth); + + DrawHeaderCell( + Content( + "featureLevel.column.description", + "Raw Keyword / Note", + "Raw shader keyword or configuration note."), + DescriptionColumnWidth); + } + } + + private static void DrawHeaderCell(GUIContent content, float width) + { + GUILayout.Label(content, EditorStyles.toolbarButton, GUILayout.Width(width), GUILayout.Height(HeaderHeight)); + } + + private static void DrawQualityBindingRow(NBShaderFeatureLevelProjectSettings settings) + { + using (new EditorGUILayout.HorizontalScope(GUILayout.Height(RowHeight))) + { + GUILayout.Label( + Content( + "featureLevel.row.quality", + "Quality Binding", + "Each Unity Quality Level belongs to exactly one NBShader tier."), + GUILayout.Width(FeatureColumnWidth), + GUILayout.Height(RowHeight)); + + for (var i = 0; i < Tiers.Length; i++) + { + var tier = Tiers[i]; + if (GUILayout.Button( + GetQualitySummaryContent(settings, tier, i), + EditorStyles.popup, + GUILayout.Width(TierColumnWidth), + GUILayout.Height(RowHeight))) + { + ShowQualityBindingMenu(settings, tier); + } + } + + DrawCostPlaceholderCell(); + DrawInfoCell( + Content( + "featureLevel.effect.quality", + "Bind Unity Quality Levels to NBShader tiers.", + "Each Unity Quality Level belongs to exactly one NBShader tier."), + EffectColumnWidth); + DrawInfoCell( + GetQualityDescriptionContent(), + DescriptionColumnWidth); + } + } + + private static bool DrawFeatureRows(NBShaderFeatureLevelProjectSettings settings) + { + var changed = false; + var rows = NBShaderFeatureLevelRowCatalog.Rows; + var allowedKeywordSets = new HashSet[Tiers.Length]; + var allowedPassFeatureSets = new HashSet[Tiers.Length]; + for (var i = 0; i < Tiers.Length; i++) + { + allowedKeywordSets[i] = settings.GetAllowedKeywordSetForReadOnlyUse(Tiers[i]); + allowedPassFeatureSets[i] = settings.GetAllowedPassFeatureSetForReadOnlyUse(Tiers[i]); + } + + for (var rowIndex = 0; rowIndex < rows.Length; rowIndex++) + { + var row = rows[rowIndex]; + if (!IsRowVisible(row)) + continue; + + using (var rowScope = new EditorGUILayout.HorizontalScope(GUILayout.Height(RowHeight))) + { + DrawFeatureRowBackground(rowScope.rect, row); + DrawFeatureNameCell(row); + + if (row.isKeyword) + { + for (var tierIndex = 0; tierIndex < Tiers.Length; tierIndex++) + { + var tier = Tiers[tierIndex]; + var isAllowed = allowedKeywordSets[tierIndex].Contains(row.keyword); + var newAllowed = DrawCellToggle(isAllowed, GUI.skin.toggle); + if (newAllowed == isAllowed) + continue; + + Undo.RecordObject(settings, Text("featureLevel.undo.changeKeyword", "Change NBShader Feature Keyword")); + settings.SetKeywordAllowed(tier, row.keyword, newAllowed); + if (newAllowed) + allowedKeywordSets[tierIndex].Add(row.keyword); + else + allowedKeywordSets[tierIndex].Remove(row.keyword); + changed = true; + } + } + else if (row.isPass) + { + for (var tierIndex = 0; tierIndex < Tiers.Length; tierIndex++) + { + var tier = Tiers[tierIndex]; + var isAllowed = allowedPassFeatureSets[tierIndex].Contains(row.passFeatureId); + var newAllowed = DrawCellToggle(isAllowed, GUI.skin.toggle); + if (newAllowed == isAllowed) + continue; + + Undo.RecordObject(settings, Text("featureLevel.undo.changePassFeature", "Change NBShader Pass Feature")); + settings.SetPassFeatureAllowed(tier, row.passFeatureId, newAllowed); + if (newAllowed) + allowedPassFeatureSets[tierIndex].Add(row.passFeatureId); + else + allowedPassFeatureSets[tierIndex].Remove(row.passFeatureId); + changed = true; + } + } + else + { + DrawEmptyTierCells(); + } + + DrawCostCell(row); + DrawInfoCell(GetEffectContent(row), EffectColumnWidth); + DrawInfoCell( + GetDescriptionContent(row), + DescriptionColumnWidth, + row.isKeyword ? EditorStyles.miniLabel : EditorStyles.centeredGreyMiniLabel); + } + } + + return changed; + } + + private static void DrawFeatureNameCell(NBShaderFeatureLevelRow row) + { + var rect = EditorGUILayout.GetControlRect( + false, + RowHeight, + GUILayout.Width(FeatureColumnWidth), + GUILayout.Height(RowHeight)); + + var hasChildren = NBShaderFeatureLevelRowCatalog.HasChildren(row); + var indent = row.depth * RowIndentWidth; + var foldoutRect = new Rect(rect.x + indent, rect.y, 14f, rect.height); + var labelRect = new Rect( + rect.x + indent + (hasChildren ? 15f : 18f), + rect.y, + Mathf.Max(0f, rect.width - indent - 18f), + rect.height); + + if (hasChildren) + { + var expanded = IsExpanded(row.key); + var newExpanded = EditorGUI.Foldout(foldoutRect, expanded, GUIContent.none, true); + if (newExpanded != expanded) + SetExpanded(row.key, newExpanded); + } + + var style = hasChildren ? EditorStyles.boldLabel : EditorStyles.label; + EditorGUI.LabelField(labelRect, GetRowContent(row), style); + } + + private static void DrawFeatureRowBackground(Rect rowRect, NBShaderFeatureLevelRow row) + { + if (!IsSectionRow(row) || Event.current.type != EventType.Repaint) + return; + + rowRect.width = TableWidth; + EditorGUI.DrawRect(rowRect, new Color(0f, 0f, 0f, EditorGUIUtility.isProSkin ? 0.22f : 0.08f)); + } + + private static bool IsSectionRow(NBShaderFeatureLevelRow row) + { + return row != null && + row.kind == NBShaderFeatureLevelRowKind.Group && + string.IsNullOrEmpty(row.parentKey); + } + + private static void DrawEmptyTierCells() + { + for (var i = 0; i < Tiers.Length; i++) + GUILayout.Space(TierColumnWidth); + } + + private static void DrawCostCell(NBShaderFeatureLevelRow row) + { + if (row != null && (row.isKeyword || row.isPass)) + { + DrawInfoCell(GetCostContent(row.performanceCost), CostColumnWidth, EditorStyles.centeredGreyMiniLabel); + return; + } + + DrawCostPlaceholderCell(); + } + + private static void DrawCostPlaceholderCell() + { + DrawInfoCell(GetNoValueContent(), CostColumnWidth, EditorStyles.centeredGreyMiniLabel); + } + + private static void DrawInfoCell(GUIContent content, float width, GUIStyle style = null) + { + GUILayout.Label( + content, + style ?? EditorStyles.miniLabel, + GUILayout.Width(width), + GUILayout.Height(RowHeight)); + } + + private static bool DrawButtons(NBShaderFeatureLevelProjectSettings settings) + { + var changed = false; + + using (new EditorGUILayout.HorizontalScope()) + { + if (GUILayout.Button(ButtonContent( + "featureLevel.resetTierKeywords", + "Reset Tier Features", + "Reset the keyword and pass matrix to the built-in defaults."))) + { + Undo.RecordObject(settings, Text("featureLevel.undo.resetTierKeywords", "Reset NBShader Tier Features")); + settings.ResetTierKeywordSetsToDefault(); + settings.ResetTierPassSetsToDefault(); + changed = true; + } + + if (GUILayout.Button(ButtonContent( + "featureLevel.resetQualityMapping", + "Reset Quality Mapping", + "Reset Unity Quality bindings using the default quality-index rule."))) + { + Undo.RecordObject(settings, Text("featureLevel.undo.resetQualityMapping", "Reset NBShader Quality Mapping")); + settings.ResetQualityMappingsToDefault(); + changed = true; + } + } + + using (new EditorGUILayout.HorizontalScope()) + { + if (GUILayout.Button(ButtonContent( + "featureLevel.openVariantCollectionBuilder", + "Open Variant Collection Builder", + "Open the NBShader variant collection builder."))) + { + NBShaderSVCBuilderWindow.Open(); + } + + if (GUILayout.Button(ButtonContent( + "featureLevel.saveCurrentAsDefault", + "Save Current Config as Default", + "Write the current tier keyword and pass matrix into the package default LevelAsset."))) + { + if (!NBShaderFeatureLevelPresetLoader.SaveDefaultFeatureSets(settings.tierKeywordSets, settings.tierPassSets)) + { + EditorUtility.DisplayDialog( + Text("featureLevel.saveCurrentAsDefault.failedTitle", "Save Default Config Failed"), + Text("featureLevel.saveCurrentAsDefault.failedMessage", "Could not write the package default LevelAsset."), + Text("featureLevel.dialog.ok", "OK")); + } + } + } + + using (new EditorGUILayout.HorizontalScope()) + { + if (GUILayout.Button(ButtonContent( + "featureLevel.applyCurrentQualityTierToLoadedMaterials", + "Apply Current Quality Tier To Loaded Materials", + "Apply the tier bound to the current Unity Quality Level to all loaded NBShader2 materials."))) + { + NBShaderEditorQualityTierWatcher.ApplyCurrentQualityTierToLoadedMaterials(); + } + + if (GUILayout.Button(ButtonContent( + "featureLevel.applyCurrentQualityTierToProjectMaterials", + "Apply Current Quality Tier To Project Materials", + "Scan Assets and apply the tier bound to the current Unity Quality Level to NBShader2 material assets."))) + { + NBShaderEditorQualityTierWatcher.ApplyCurrentQualityTierToProjectMaterials(); + } + } + + return changed; + } + + private static void ShowQualityBindingMenu(NBShaderFeatureLevelProjectSettings settings, NBShaderFeatureTier targetTier) + { + var menu = new GenericMenu(); + var mappings = settings.qualityTierMappings; + if (mappings == null || mappings.Length == 0) + { + menu.AddDisabledItem(new GUIContent(Text("featureLevel.quality.noLevels", "No Quality Levels"))); + menu.ShowAsContext(); + return; + } + + for (var i = 0; i < mappings.Length; i++) + { + var mapping = mappings[i]; + if (mapping == null || string.IsNullOrEmpty(mapping.qualityName)) + continue; + + var qualityName = mapping.qualityName; + NBShaderFeatureTier currentTier; + var isCurrentTier = settings.TryGetTierForQualityName(qualityName, out currentTier) && currentTier == targetTier; + if (isCurrentTier) + { + menu.AddDisabledItem(new GUIContent("✓ " + qualityName)); + continue; + } + + menu.AddItem(new GUIContent(qualityName), false, () => + { + Undo.RecordObject(settings, Text("featureLevel.undo.changeQualityBinding", "Change NBShader Quality Binding")); + settings.MoveQualityToTier(qualityName, targetTier); + settings.SaveProjectSettings(); + UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); + }); + } + + menu.ShowAsContext(); + } + + private static bool DrawCellToggle(bool value, GUIStyle style) + { + bool result; + using (new GUILayout.HorizontalScope(GUILayout.Width(TierColumnWidth), GUILayout.Height(RowHeight))) + { + GUILayout.FlexibleSpace(); + result = GUILayout.Toggle( + value, + GUIContent.none, + style, + GUILayout.Width(18f), + GUILayout.Height(RowHeight)); + GUILayout.FlexibleSpace(); + } + + return result; + } + + private static void DrawTableSeparator() + { + var rect = EditorGUILayout.GetControlRect(false, 1f, GUILayout.Width(TableWidth)); + EditorGUI.DrawRect(rect, new Color(0f, 0f, 0f, 0.25f)); + } + + private static bool IsRowVisible(NBShaderFeatureLevelRow row) + { + var parentKey = row.parentKey; + while (!string.IsNullOrEmpty(parentKey)) + { + if (!IsExpanded(parentKey)) + return false; + + NBShaderFeatureLevelRow parent; + parentKey = NBShaderFeatureLevelRowCatalog.TryGetRow(parentKey, out parent) ? parent.parentKey : null; + } + + return true; + } + + private static bool IsExpanded(string key) + { + return SessionState.GetBool(FoldoutSessionPrefix + key, true); + } + + private static void SetExpanded(string key, bool expanded) + { + SessionState.SetBool(FoldoutSessionPrefix + key, expanded); + } + + private static GUIContent GetTierContent(NBShaderFeatureTier tier) + { + switch (tier) + { + case NBShaderFeatureTier.Low: + return NBShaderInspectorLocalization.MakeContent( + "inspector.toolbar.tierLow.label", + "Low", + "inspector.toolbar.tier.tip", + "NBShader feature tier"); + case NBShaderFeatureTier.Medium: + return NBShaderInspectorLocalization.MakeContent( + "inspector.toolbar.tierMedium.label", + "Medium", + "inspector.toolbar.tier.tip", + "NBShader feature tier"); + case NBShaderFeatureTier.High: + return NBShaderInspectorLocalization.MakeContent( + "inspector.toolbar.tierHigh.label", + "High", + "inspector.toolbar.tier.tip", + "NBShader feature tier"); + default: + return NBShaderInspectorLocalization.MakeContent( + "inspector.toolbar.tierUltra.label", + "Ultra", + "inspector.toolbar.tier.tip", + "NBShader feature tier"); + } + } + + private static GUIContent GetRowContent(NBShaderFeatureLevelRow row) + { + return GetCachedRowContent(row).rowContent; + } + + private static GUIContent BuildRowContent(NBShaderFeatureLevelRow row) + { + if (row.isKeyword) + return BuildKeywordContent(row.keyword, row.labelFallback); + + if (row.isPass) + return BuildPassContent(row.passFeatureId, row.labelFallback); + + return NBShaderInspectorLocalization.MakeContent( + "inspector.featureLevel.group." + row.key + ".label", + row.labelFallback, + "inspector.featureLevel.group." + row.key + ".tip", + Text("featureLevel.group.tooltip", "Click the foldout to show or hide child rows.")); + } + + private static GUIContent BuildKeywordContent(string keyword, string fallback) + { + var label = NBShaderInspectorLocalization.Get( + "inspector.featureLevel.keyword." + keyword + ".label", + string.IsNullOrEmpty(fallback) ? keyword : fallback); + var tooltipFormat = Text( + "featureLevel.keyword.tooltip", + "Raw keyword: {0}. Unchecked in a tier strips variants using this Catalog keyword."); + return new GUIContent(label, string.Format(tooltipFormat, keyword)); + } + + private static GUIContent BuildPassContent(string passFeatureId, string fallback) + { + string passName; + string displayName; + if (!NBShaderFeatureLevelCatalog.TryGetManagedPassFeatureInfo(passFeatureId, out passName, out displayName)) + { + passName = passFeatureId; + displayName = string.IsNullOrEmpty(fallback) ? passFeatureId : fallback; + } + + var label = NBShaderInspectorLocalization.Get( + "inspector.featureLevel.pass." + passFeatureId + ".label", + string.IsNullOrEmpty(fallback) ? displayName : fallback); + var tooltipFormat = Text( + "featureLevel.pass.tooltip", + "Shader pass: {0}. Unchecked in a tier strips or gates this pass when material intent requires it."); + return new GUIContent(label, string.Format(tooltipFormat, passName)); + } + + private static GUIContent GetCostContent(NBShaderFeaturePerformanceCost cost) + { + GUIContent content; + if (s_CostContentCache.TryGetValue(cost, out content)) + return content; + + string key; + string fallback; + switch (cost) + { + case NBShaderFeaturePerformanceCost.Low: + key = "featureLevel.cost.low"; + fallback = "Low"; + break; + case NBShaderFeaturePerformanceCost.Medium: + key = "featureLevel.cost.medium"; + fallback = "Medium"; + break; + case NBShaderFeaturePerformanceCost.High: + key = "featureLevel.cost.high"; + fallback = "High"; + break; + default: + key = "featureLevel.cost.ultra"; + fallback = "Ultra"; + break; + } + + content = new GUIContent( + Text(key, fallback), + Text("featureLevel.cost.tooltip", "Estimated shader performance cost for this feature.")); + s_CostContentCache[cost] = content; + return content; + } + + private static GUIContent GetEffectContent(NBShaderFeatureLevelRow row) + { + return GetCachedRowContent(row).effectContent; + } + + private static GUIContent BuildEffectContent(NBShaderFeatureLevelRow row) + { + if (row.isKeyword) + { + var effect = NBShaderInspectorLocalization.Get( + "inspector.featureLevel.keyword." + row.keyword + ".effect", + string.IsNullOrEmpty(row.effectFallback) ? row.keyword : row.effectFallback); + return new GUIContent(effect, effect); + } + + if (row.isPass) + { + var effect = NBShaderInspectorLocalization.Get( + "inspector.featureLevel.pass." + row.passFeatureId + ".effect", + string.IsNullOrEmpty(row.effectFallback) ? row.passFeatureId : row.effectFallback); + return new GUIContent(effect, effect); + } + + var groupTip = NBShaderInspectorLocalization.GetTooltip( + "inspector.featureLevel.group." + row.key + ".label", + "inspector.featureLevel.group." + row.key + ".tip", + Text("featureLevel.group.tooltip", "Click the foldout to show or hide child rows.")); + return new GUIContent(groupTip, groupTip); + } + + private static GUIContent GetDescriptionContent(NBShaderFeatureLevelRow row) + { + return GetCachedRowContent(row).descriptionContent; + } + + private static GUIContent BuildDescriptionContent(NBShaderFeatureLevelRow row) + { + if (row.isKeyword) + return new GUIContent(row.keyword, row.keyword); + + if (row.isPass) + { + string passName; + string displayName; + if (NBShaderFeatureLevelCatalog.TryGetManagedPassFeatureInfo(row.passFeatureId, out passName, out displayName)) + return new GUIContent(passName, row.passFeatureId); + + return new GUIContent(row.passFeatureId, row.passFeatureId); + } + + return new GUIContent( + Text("featureLevel.desc.group", "Group"), + Text("featureLevel.group.tooltip", "Click the foldout to show or hide child rows.")); + } + + private static GUIContent GetNoValueContent() + { + if (s_NoValueContent != null) + return s_NoValueContent; + + var text = Text("featureLevel.desc.none", "—"); + s_NoValueContent = new GUIContent(text, text); + return s_NoValueContent; + } + + private static GUIContent GetProviderLabelContent() + { + EnsureContentCacheForCurrentLanguage(); + + if (s_ProviderLabelContent == null) + s_ProviderLabelContent = new GUIContent(Text("featureLevel.providerLabel", "NBShader Feature Levels")); + + return s_ProviderLabelContent; + } + + private static GUIContent GetQualityDescriptionContent() + { + if (s_QualityDescriptionContent == null) + { + var text = Text("featureLevel.desc.quality", "Unity Quality Level"); + s_QualityDescriptionContent = new GUIContent(text, text); + } + + return s_QualityDescriptionContent; + } + + private static GUIContent GetQualitySummaryContent( + NBShaderFeatureLevelProjectSettings settings, + NBShaderFeatureTier tier, + int tierIndex) + { + EnsureQualitySummaryCache(settings); + + var content = s_QualitySummaryContents[tierIndex]; + if (content == null) + { + content = new GUIContent(); + s_QualitySummaryContents[tierIndex] = content; + } + + content.text = s_QualitySummaryTexts[tierIndex]; + content.tooltip = GetQualityMenuTipText(); + return content; + } + + private static void EnsureQualitySummaryCache(NBShaderFeatureLevelProjectSettings settings) + { + var mappings = settings.qualityTierMappings; + var hash = GetQualitySummaryHash(mappings); + if (s_QualitySummaryTexts[0] != null && s_QualitySummaryHash == hash) + return; + + s_QualitySummaryHash = hash; + var noneText = Text("featureLevel.quality.none", "—"); + for (var tierIndex = 0; tierIndex < Tiers.Length; tierIndex++) + { + s_QualitySummaryBuilder.Length = 0; + if (mappings != null) + { + var tier = Tiers[tierIndex]; + for (var i = 0; i < mappings.Length; i++) + { + var mapping = mappings[i]; + if (mapping == null || + mapping.tier != tier || + string.IsNullOrEmpty(mapping.qualityName)) + { + continue; + } + + if (s_QualitySummaryBuilder.Length > 0) + s_QualitySummaryBuilder.Append(", "); + s_QualitySummaryBuilder.Append(mapping.qualityName); + } + } + + s_QualitySummaryTexts[tierIndex] = + s_QualitySummaryBuilder.Length == 0 + ? noneText + : s_QualitySummaryBuilder.ToString(); + } + + s_QualitySummaryBuilder.Length = 0; + } + + private static int GetQualitySummaryHash(NBShaderQualityTierMapping[] mappings) + { + unchecked + { + var hash = 17; + if (mappings == null) + return hash; + + for (var i = 0; i < mappings.Length; i++) + { + var mapping = mappings[i]; + hash = hash * 31 + (mapping != null ? (int)mapping.tier : -1); + hash = hash * 31 + (mapping != null && mapping.qualityName != null + ? StringComparer.Ordinal.GetHashCode(mapping.qualityName) + : 0); + } + + return hash; + } + } + + private static string GetQualityMenuTipText() + { + if (s_QualityMenuTipText == null) + { + s_QualityMenuTipText = Text( + "featureLevel.quality.menuTip", + "Click to move Unity Quality levels to this NBShader tier."); + } + + return s_QualityMenuTipText; + } + + private static RowContentCache GetCachedRowContent(NBShaderFeatureLevelRow row) + { + RowContentCache cache; + if (!s_RowContentCache.TryGetValue(row.key, out cache)) + { + cache = new RowContentCache + { + rowContent = BuildRowContent(row), + effectContent = BuildEffectContent(row), + descriptionContent = BuildDescriptionContent(row) + }; + s_RowContentCache.Add(row.key, cache); + } + + return cache; + } + + private static void EnsureContentCacheForCurrentLanguage() + { + var language = NBShaderInspectorLocalization.CurrentLanguage; + if (string.Equals(s_ContentCacheLanguage, language, StringComparison.Ordinal)) + return; + + s_ContentCacheLanguage = language; + s_RowContentCache.Clear(); + s_CostContentCache.Clear(); + s_ProviderLabelContent = null; + s_QualityDescriptionContent = null; + s_NoValueContent = null; + s_QualityMenuTipText = null; + s_QualitySummaryHash = 0; + for (var i = 0; i < s_QualitySummaryContents.Length; i++) + { + s_QualitySummaryContents[i] = null; + s_QualitySummaryTexts[i] = null; + } + } + + private static GUIContent Content(string key, string fallback, string tip = "") + { + return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip); + } + + private static GUIContent ButtonContent(string key, string fallback, string tip = "") + { + return NBShaderInspectorLocalization.MakeContent("inspector." + key + ".button", fallback, null, tip); + } + + private static string Text(string key, string fallback) + { + return NBShaderInspectorLocalization.GetInspectorText(key, fallback); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelSettingsProvider.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelSettingsProvider.cs.meta new file mode 100644 index 00000000..e1b0a676 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelSettingsProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 278a2a702fc5d47e3a7e5c61468cc2c7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelTypes.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelTypes.cs new file mode 100644 index 00000000..a8617a23 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelTypes.cs @@ -0,0 +1,26 @@ +using System; +using NBShader; + +namespace NBShaders2.Editor.FeatureLevel +{ + [Serializable] + public sealed class NBShaderFeatureTierKeywordSet + { + public NBShaderFeatureTier tier; + public string[] allowedKeywords = new string[0]; + } + + [Serializable] + public sealed class NBShaderFeatureTierPassSet + { + public NBShaderFeatureTier tier; + public string[] allowedPassFeatures = new string[0]; + } + + [Serializable] + public sealed class NBShaderQualityTierMapping + { + public string qualityName; + public NBShaderFeatureTier tier; + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelTypes.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelTypes.cs.meta new file mode 100644 index 00000000..0ee0757c --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureLevelTypes.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24ec2067d0e81465ebeab015048983e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureRuntimeSettingsEditor.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureRuntimeSettingsEditor.cs new file mode 100644 index 00000000..c94340e8 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureRuntimeSettingsEditor.cs @@ -0,0 +1,58 @@ +using NBShader; +using NBShaderEditor; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor.FeatureLevel +{ + [CustomEditor(typeof(NBShaderFeatureRuntimeSettings))] + public sealed class NBShaderFeatureRuntimeSettingsEditor : UnityEditor.Editor + { + public override void OnInspectorGUI() + { + DrawSyncButton(); + + EditorGUILayout.Space(); + DrawDefaultInspector(); + } + + private void DrawSyncButton() + { + var settings = (NBShaderFeatureRuntimeSettings)target; + using (new EditorGUI.DisabledScope(settings == null)) + { + if (!GUILayout.Button(ButtonContent( + "featureRuntimeSettings.updateFromProjectSettings", + "根据当前ProjectSetting更新配置", + "Write the current NBShader Project Settings data into this runtime settings asset."))) + { + return; + } + } + + Undo.RecordObject( + settings, + Text( + "featureRuntimeSettings.updateFromProjectSettings.undo", + "Update NBShader Runtime Settings From Project Settings")); + + if (NBShaderRuntimeSettingsSynchronizer.WriteProjectSettingsToRuntimeAsset(settings)) + { + EditorUtility.DisplayDialog( + Text("featureRuntimeSettings.updateFromProjectSettings.successTitle", "Runtime Settings Updated"), + Text("featureRuntimeSettings.updateFromProjectSettings.successMessage", "The current NBShader Project Settings data was written to this runtime settings asset."), + Text("featureLevel.dialog.ok", "OK")); + } + } + + private static GUIContent ButtonContent(string key, string fallback, string tip) + { + return NBShaderInspectorLocalization.MakeInspectorContent(key + ".button", fallback, tip); + } + + private static string Text(string key, string fallback) + { + return NBShaderInspectorLocalization.GetInspectorText(key, fallback); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureRuntimeSettingsEditor.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureRuntimeSettingsEditor.cs.meta new file mode 100644 index 00000000..e764cdc9 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderFeatureRuntimeSettingsEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86834a41402844679aead46b69ad7fdf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderRuntimeSettingsSynchronizer.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderRuntimeSettingsSynchronizer.cs new file mode 100644 index 00000000..aab5ce2d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderRuntimeSettingsSynchronizer.cs @@ -0,0 +1,241 @@ +using System.Collections.Generic; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor.FeatureLevel +{ + public static class NBShaderRuntimeSettingsSynchronizer + { + public const string DefaultGeneratedRuntimeSettingsAssetPath = + "Assets/NBShaderGenerated/RuntimeSettings/NBShaderFeatureRuntimeSettings.asset"; + + private static bool s_DefaultGeneratedRuntimeSettingsWarningLogged; + + public static bool WriteProjectSettingsToRuntimeAsset(NBShaderFeatureRuntimeSettings asset) + { + if (asset == null) + { + Debug.LogWarning("NBShader runtime settings asset is null. Pass an explicit NBShaderFeatureRuntimeSettings asset before writing."); + return false; + } + + var settings = NBShaderFeatureLevelProjectSettings.instance; + settings.EnsureInitialized(); + ApplyProjectSettingsToRuntimeObject(asset, settings); + EditorUtility.SetDirty(asset); + AssetDatabase.SaveAssetIfDirty(asset); + return true; + } + + public static bool WriteProjectSettingsSnapshotToRuntimeAssetNoSave(NBShaderFeatureRuntimeSettings asset) + { + if (asset == null) + { + Debug.LogWarning("NBShader runtime settings asset is null. Pass an explicit NBShaderFeatureRuntimeSettings asset before writing."); + return false; + } + + ApplyProjectSettingsSnapshotToRuntimeObjectNoSave(asset, NBShaderFeatureLevelProjectSettings.instance); + EditorUtility.SetDirty(asset); + AssetDatabase.SaveAssetIfDirty(asset); + return true; + } + + public static NBShaderFeatureRuntimeSettings WriteDefaultGeneratedRuntimeSettingsAsset(out string assetPath) + { + assetPath = DefaultGeneratedRuntimeSettingsAssetPath; + LogDefaultGeneratedRuntimeSettingsWarningOnce(assetPath); + + var asset = LoadOrCreateRuntimeSettingsAsset(assetPath); + if (asset == null) + return null; + + return WriteProjectSettingsToRuntimeAsset(asset) ? asset : null; + } + + public static NBShaderFeatureRuntimeSettings WriteRuntimeSettingsAssetOrDefault( + NBShaderFeatureRuntimeSettings explicitAsset, + out string assetPath) + { + if (explicitAsset == null) + return WriteDefaultGeneratedRuntimeSettingsAsset(out assetPath); + + assetPath = AssetDatabase.GetAssetPath(explicitAsset); + return WriteProjectSettingsToRuntimeAsset(explicitAsset) ? explicitAsset : null; + } + + private static void ApplyProjectSettingsToRuntimeObject( + NBShaderFeatureRuntimeSettings asset, + NBShaderFeatureLevelProjectSettings settings) + { + asset.lowAllowedKeywords = ToCatalogOrderedKeywords(settings.GetAllowedKeywordSet(NBShaderFeatureTier.Low)); + asset.mediumAllowedKeywords = ToCatalogOrderedKeywords(settings.GetAllowedKeywordSet(NBShaderFeatureTier.Medium)); + asset.highAllowedKeywords = ToCatalogOrderedKeywords(settings.GetAllowedKeywordSet(NBShaderFeatureTier.High)); + asset.ultraAllowedKeywords = ToCatalogOrderedKeywords(settings.GetAllowedKeywordSet(NBShaderFeatureTier.Ultra)); + + asset.lowAllowedPassFeatures = ToCatalogOrderedPassFeatures(settings.GetAllowedPassFeatureSet(NBShaderFeatureTier.Low)); + asset.mediumAllowedPassFeatures = ToCatalogOrderedPassFeatures(settings.GetAllowedPassFeatureSet(NBShaderFeatureTier.Medium)); + asset.highAllowedPassFeatures = ToCatalogOrderedPassFeatures(settings.GetAllowedPassFeatureSet(NBShaderFeatureTier.High)); + asset.ultraAllowedPassFeatures = ToCatalogOrderedPassFeatures(settings.GetAllowedPassFeatureSet(NBShaderFeatureTier.Ultra)); + + asset.qualityTierMappings = ConvertQualityMappings(settings.qualityTierMappings); + } + + private static void ApplyProjectSettingsSnapshotToRuntimeObjectNoSave( + NBShaderFeatureRuntimeSettings asset, + NBShaderFeatureLevelProjectSettings settings) + { + asset.lowAllowedKeywords = ToCatalogOrderedKeywords(settings.GetAllowedKeywordSetForBuildInfoNoSave(NBShaderFeatureTier.Low)); + asset.mediumAllowedKeywords = ToCatalogOrderedKeywords(settings.GetAllowedKeywordSetForBuildInfoNoSave(NBShaderFeatureTier.Medium)); + asset.highAllowedKeywords = ToCatalogOrderedKeywords(settings.GetAllowedKeywordSetForBuildInfoNoSave(NBShaderFeatureTier.High)); + asset.ultraAllowedKeywords = ToCatalogOrderedKeywords(settings.GetAllowedKeywordSetForBuildInfoNoSave(NBShaderFeatureTier.Ultra)); + + asset.lowAllowedPassFeatures = ToCatalogOrderedPassFeatures(settings.GetAllowedPassFeatureSetForBuildInfoNoSave(NBShaderFeatureTier.Low)); + asset.mediumAllowedPassFeatures = ToCatalogOrderedPassFeatures(settings.GetAllowedPassFeatureSetForBuildInfoNoSave(NBShaderFeatureTier.Medium)); + asset.highAllowedPassFeatures = ToCatalogOrderedPassFeatures(settings.GetAllowedPassFeatureSetForBuildInfoNoSave(NBShaderFeatureTier.High)); + asset.ultraAllowedPassFeatures = ToCatalogOrderedPassFeatures(settings.GetAllowedPassFeatureSetForBuildInfoNoSave(NBShaderFeatureTier.Ultra)); + + asset.qualityTierMappings = ConvertQualityMappingsNoSave(settings); + } + + private static NBShaderFeatureRuntimeSettings.QualityTierMapping[] ConvertQualityMappings(NBShaderQualityTierMapping[] source) + { + if (source == null || source.Length == 0) + return new NBShaderFeatureRuntimeSettings.QualityTierMapping[0]; + + var result = new NBShaderFeatureRuntimeSettings.QualityTierMapping[source.Length]; + for (var i = 0; i < source.Length; i++) + { + var item = source[i]; + result[i] = new NBShaderFeatureRuntimeSettings.QualityTierMapping + { + qualityName = item != null ? item.qualityName : string.Empty, + tier = item != null ? item.tier : NBShaderFeatureTier.Ultra + }; + } + + return result; + } + + private static NBShaderFeatureRuntimeSettings.QualityTierMapping[] ConvertQualityMappingsNoSave(NBShaderFeatureLevelProjectSettings settings) + { + var qualityNames = QualitySettings.names; + if (qualityNames == null || qualityNames.Length == 0) + qualityNames = new[] { "Default" }; + + var result = new NBShaderFeatureRuntimeSettings.QualityTierMapping[qualityNames.Length]; + for (var i = 0; i < qualityNames.Length; i++) + { + var qualityName = qualityNames[i]; + NBShaderFeatureTier tier; + if (!settings.TryGetTierForQualityNameNoSave(qualityName, out tier)) + tier = NBShaderFeatureTier.Ultra; + + result[i] = new NBShaderFeatureRuntimeSettings.QualityTierMapping + { + qualityName = qualityName, + tier = tier + }; + } + + return result; + } + + private static string[] ToCatalogOrderedKeywords(HashSet allowed) + { + return ToCatalogOrderedArray(allowed, NBShaderFeatureCatalog.RawKeywords); + } + + private static string[] ToCatalogOrderedPassFeatures(HashSet allowed) + { + return ToCatalogOrderedArray(allowed, NBShaderPassFeatureCatalog.RawPassFeatureIds); + } + + private static string[] ToCatalogOrderedArray(HashSet allowed, string[] catalogOrder) + { + if (allowed == null || catalogOrder == null) + return new string[0]; + + var result = new List(); + for (var i = 0; i < catalogOrder.Length; i++) + { + var value = catalogOrder[i]; + if (allowed.Contains(value)) + result.Add(value); + } + + return result.ToArray(); + } + + private static NBShaderFeatureRuntimeSettings LoadOrCreateRuntimeSettingsAsset(string assetPath) + { + var existing = AssetDatabase.LoadAssetAtPath(assetPath); + if (existing == null) + { + if (!EnsureAssetFolder(assetPath)) + return null; + + var asset = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(asset, assetPath); + return asset; + } + + var runtimeSettings = existing as NBShaderFeatureRuntimeSettings; + if (runtimeSettings != null) + return runtimeSettings; + + Debug.LogError("NBShader default runtime settings output path is occupied by another asset type: " + assetPath); + return null; + } + + private static bool EnsureAssetFolder(string assetPath) + { + var slashIndex = assetPath.LastIndexOf('/'); + if (slashIndex <= 0) + return true; + + var folderPath = assetPath.Substring(0, slashIndex); + var parts = folderPath.Split('/'); + if (parts.Length == 0 || parts[0] != "Assets") + { + Debug.LogError("NBShader default runtime settings asset path must be under Assets: " + assetPath); + return false; + } + + var current = "Assets"; + for (var i = 1; i < parts.Length; i++) + { + var part = parts[i]; + if (string.IsNullOrEmpty(part)) + continue; + + var next = current + "/" + part; + if (!AssetDatabase.IsValidFolder(next)) + AssetDatabase.CreateFolder(current, part); + + if (!AssetDatabase.IsValidFolder(next)) + { + Debug.LogError("Failed to create NBShader runtime settings folder: " + next); + return false; + } + + current = next; + } + + return true; + } + + private static void LogDefaultGeneratedRuntimeSettingsWarningOnce(string assetPath) + { + if (s_DefaultGeneratedRuntimeSettingsWarningLogged) + return; + + s_DefaultGeneratedRuntimeSettingsWarningLogged = true; + Debug.LogWarning( + "NBShader runtime settings asset was not explicitly specified. Generated one from current Project Settings at " + + assetPath + + ". Include this asset in the player, Addressables, Resources, or shader AssetBundle before runtime code passes it to NBShaderFeatureRuntime.ApplyTier."); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderRuntimeSettingsSynchronizer.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderRuntimeSettingsSynchronizer.cs.meta new file mode 100644 index 00000000..41d8ab37 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderRuntimeSettingsSynchronizer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24198ba1f30a4441782ea031021cfbfb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderSVCBuilderWindow.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderSVCBuilderWindow.cs new file mode 100644 index 00000000..2bf3aedf --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderSVCBuilderWindow.cs @@ -0,0 +1,290 @@ +using System.Collections.Generic; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor.FeatureLevel +{ + internal sealed class NBShaderSVCBuilderWindow : EditorWindow + { + [SerializeField] private List m_SearchFolders = new List(); + [SerializeField] private string m_OutputFolder = NBShaderVariantCollectionBuilder.DefaultOutputFolder; + [SerializeField] private int m_TierMask = AllTierMask; + + private Vector2 m_Scroll; + private NBShaderVariantCollectionTierResult[] m_Previews = new NBShaderVariantCollectionTierResult[0]; + private string m_Status = string.Empty; + + private const int AllTierMask = + (1 << (int)NBShaderFeatureTier.Low) | + (1 << (int)NBShaderFeatureTier.Medium) | + (1 << (int)NBShaderFeatureTier.High) | + (1 << (int)NBShaderFeatureTier.Ultra); + + private static readonly NBShaderFeatureTier[] Tiers = + { + NBShaderFeatureTier.Low, + NBShaderFeatureTier.Medium, + NBShaderFeatureTier.High, + NBShaderFeatureTier.Ultra + }; + + internal static void Open() + { + var window = GetWindow("NBShader Variant Collection Builder"); + window.minSize = new Vector2(620f, 420f); + window.Show(); + } + + private void OnEnable() + { + if (m_SearchFolders == null) + m_SearchFolders = new List(); + if (m_SearchFolders.Count == 0) + m_SearchFolders.Add("Assets"); + if (string.IsNullOrEmpty(m_OutputFolder)) + m_OutputFolder = NBShaderVariantCollectionBuilder.DefaultOutputFolder; + if (m_TierMask == 0) + m_TierMask = AllTierMask; + } + + private void OnGUI() + { + m_Scroll = EditorGUILayout.BeginScrollView(m_Scroll); + DrawSearchFolders(); + EditorGUILayout.Space(8f); + DrawOutputFolder(); + EditorGUILayout.Space(8f); + DrawTierSelection(); + EditorGUILayout.Space(8f); + DrawActions(); + EditorGUILayout.Space(8f); + DrawPreview(); + EditorGUILayout.EndScrollView(); + } + + private void DrawSearchFolders() + { + EditorGUILayout.LabelField("Material Search Folders", EditorStyles.boldLabel); + for (var i = 0; i < m_SearchFolders.Count; i++) + { + EditorGUILayout.BeginHorizontal(); + m_SearchFolders[i] = EditorGUILayout.TextField(m_SearchFolders[i]); + if (GUILayout.Button("...", GUILayout.Width(28f))) + { + var folder = PickProjectFolder(m_SearchFolders[i]); + if (!string.IsNullOrEmpty(folder)) + m_SearchFolders[i] = folder; + } + + if (GUILayout.Button("-", GUILayout.Width(28f))) + { + m_SearchFolders.RemoveAt(i); + GUIUtility.ExitGUI(); + } + EditorGUILayout.EndHorizontal(); + } + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Add Folder")) + { + var folder = PickProjectFolder("Assets"); + if (!string.IsNullOrEmpty(folder)) + AddSearchFolder(folder); + } + + if (GUILayout.Button("Add Selected")) + { + AddSelectedFolders(); + } + EditorGUILayout.EndHorizontal(); + } + + private void DrawOutputFolder() + { + EditorGUILayout.LabelField("Output Folder", EditorStyles.boldLabel); + EditorGUILayout.BeginHorizontal(); + m_OutputFolder = EditorGUILayout.TextField(m_OutputFolder); + if (GUILayout.Button("...", GUILayout.Width(28f))) + { + var folder = PickProjectFolder(m_OutputFolder); + if (!string.IsNullOrEmpty(folder)) + m_OutputFolder = folder; + } + EditorGUILayout.EndHorizontal(); + } + + private void DrawTierSelection() + { + EditorGUILayout.LabelField("Build Tiers", EditorStyles.boldLabel); + using (new EditorGUILayout.HorizontalScope()) + { + for (var i = 0; i < Tiers.Length; i++) + DrawTierToggle(Tiers[i]); + + GUILayout.FlexibleSpace(); + if (GUILayout.Button("All", GUILayout.Width(56f))) + SetTierMask(AllTierMask); + } + + if (!HasSelectedTier()) + EditorGUILayout.HelpBox("Select at least one tier before previewing or generating SVC assets.", MessageType.Warning); + } + + private void DrawTierToggle(NBShaderFeatureTier tier) + { + var selected = IsTierSelected(tier); + var newSelected = EditorGUILayout.ToggleLeft(tier.ToString(), selected, GUILayout.Width(92f)); + if (newSelected == selected) + return; + + var mask = 1 << (int)tier; + if (newSelected) + SetTierMask(m_TierMask | mask); + else + SetTierMask(m_TierMask & ~mask); + } + + private void DrawActions() + { + EditorGUILayout.BeginHorizontal(); + using (new EditorGUI.DisabledScope(!HasSelectedTier())) + { + if (GUILayout.Button("Preview", GUILayout.Height(28f))) + Preview(); + } + + using (new EditorGUI.DisabledScope(!HasSelectedTier() || m_Previews == null || m_Previews.Length == 0)) + { + if (GUILayout.Button("Generate SVC", GUILayout.Height(28f))) + Generate(); + } + EditorGUILayout.EndHorizontal(); + + if (!string.IsNullOrEmpty(m_Status)) + EditorGUILayout.HelpBox(m_Status, MessageType.Info); + } + + private void DrawPreview() + { + if (m_Previews == null || m_Previews.Length == 0) + return; + + EditorGUILayout.LabelField("Preview", EditorStyles.boldLabel); + using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) + { + DrawPreviewHeader(); + for (var i = 0; i < m_Previews.Length; i++) + { + var preview = m_Previews[i]; + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(preview.tier.ToString(), GUILayout.Width(90f)); + EditorGUILayout.LabelField(preview.materialCount.ToString(), GUILayout.Width(90f)); + EditorGUILayout.LabelField(preview.passCount.ToString(), GUILayout.Width(70f)); + EditorGUILayout.LabelField(preview.variantCount.ToString(), GUILayout.Width(90f)); + EditorGUILayout.LabelField(preview.outputAssetPath ?? string.Empty); + EditorGUILayout.EndHorizontal(); + } + } + } + + private static void DrawPreviewHeader() + { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + EditorGUILayout.LabelField("Tier", EditorStyles.boldLabel, GUILayout.Width(90f)); + EditorGUILayout.LabelField("Materials", EditorStyles.boldLabel, GUILayout.Width(90f)); + EditorGUILayout.LabelField("Passes", EditorStyles.boldLabel, GUILayout.Width(70f)); + EditorGUILayout.LabelField("Variants", EditorStyles.boldLabel, GUILayout.Width(90f)); + EditorGUILayout.LabelField("Output", EditorStyles.boldLabel); + EditorGUILayout.EndHorizontal(); + } + + private void Preview() + { + var selectedTiers = GetSelectedTiers(); + var result = NBShaderVariantCollectionBuilder.Preview(m_SearchFolders, m_OutputFolder, selectedTiers); + m_Previews = result.tiers; + m_Status = string.Format( + "Found {0} NBShader materials in {1} valid folder(s). Previewed {2} tier(s) and did not write assets.", + result.materialCount, + result.validSearchFolderCount, + selectedTiers.Length); + } + + private void Generate() + { + var result = NBShaderVariantCollectionBuilder.Generate(m_SearchFolders, m_OutputFolder, GetSelectedTiers()); + if (result.hasError) + { + EditorUtility.DisplayDialog("Generate NBShader SVC", result.firstErrorMessage, "OK"); + m_Previews = result.tiers; + return; + } + + m_Previews = result.tiers; + m_Status = string.Format("Generated {0} NBShader shader variant collection asset(s).", result.generatedCount); + } + + private void AddSelectedFolders() + { + var guids = Selection.assetGUIDs; + for (var i = 0; i < guids.Length; i++) + { + var path = AssetDatabase.GUIDToAssetPath(guids[i]); + if (AssetDatabase.IsValidFolder(path)) + AddSearchFolder(path); + } + } + + private void AddSearchFolder(string folder) + { + folder = NBShaderVariantCollectionBuilder.NormalizeAssetPath(folder); + if (string.IsNullOrEmpty(folder)) + return; + if (!m_SearchFolders.Contains(folder)) + m_SearchFolders.Add(folder); + } + + private static string PickProjectFolder(string current) + { + var start = AssetDatabase.IsValidFolder(current) ? current : "Assets"; + var absoluteStart = NBShaderVariantCollectionBuilder.ToAbsolutePath(start); + var picked = EditorUtility.OpenFolderPanel("Select Project Folder", absoluteStart, string.Empty); + return NBShaderVariantCollectionBuilder.NormalizeAssetPath(picked); + } + + private bool HasSelectedTier() + { + return (m_TierMask & AllTierMask) != 0; + } + + private bool IsTierSelected(NBShaderFeatureTier tier) + { + return (m_TierMask & (1 << (int)tier)) != 0; + } + + private NBShaderFeatureTier[] GetSelectedTiers() + { + var result = new List(); + for (var i = 0; i < Tiers.Length; i++) + { + var tier = Tiers[i]; + if (IsTierSelected(tier)) + result.Add(tier); + } + + return result.ToArray(); + } + + private void SetTierMask(int tierMask) + { + tierMask &= AllTierMask; + if (m_TierMask == tierMask) + return; + + m_TierMask = tierMask; + m_Previews = new NBShaderVariantCollectionTierResult[0]; + m_Status = string.Empty; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderSVCBuilderWindow.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderSVCBuilderWindow.cs.meta new file mode 100644 index 00000000..b5e9763e --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderSVCBuilderWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1a45eb1f5ea442aa4193608a1b355a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantCollectionBuilder.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantCollectionBuilder.cs new file mode 100644 index 00000000..ff1ceb74 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantCollectionBuilder.cs @@ -0,0 +1,474 @@ +using System; +using System.Collections.Generic; +using System.IO; +using NBShader; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NBShaders2.Editor.FeatureLevel +{ + public static class NBShaderVariantCollectionBuilder + { + public const string DefaultOutputFolder = "Assets/NBShader/ShaderVariantCollections"; + + private static readonly NBShaderFeatureTier[] Tiers = + { + NBShaderFeatureTier.Low, + NBShaderFeatureTier.Medium, + NBShaderFeatureTier.High, + NBShaderFeatureTier.Ultra + }; + + public static NBShaderVariantCollectionBuildResult Preview(IEnumerable searchFolders, string outputFolder) + { + return Preview(searchFolders, outputFolder, null); + } + + public static NBShaderVariantCollectionBuildResult Preview( + IEnumerable searchFolders, + string outputFolder, + IEnumerable tiers) + { + var validFolders = GetValidSearchFolders(searchFolders); + var materials = CollectMaterialsInValidFolders(validFolders); + return BuildResult(validFolders, materials, NormalizeOutputFolder(outputFolder), NormalizeTiers(tiers), false); + } + + public static NBShaderVariantCollectionBuildResult Generate(IEnumerable searchFolders, string outputFolder) + { + return Generate(searchFolders, outputFolder, null); + } + + public static NBShaderVariantCollectionBuildResult Generate( + IEnumerable searchFolders, + string outputFolder, + IEnumerable tiers) + { + var validFolders = GetValidSearchFolders(searchFolders); + var materials = CollectMaterialsInValidFolders(validFolders); + var normalizedOutputFolder = NormalizeOutputFolder(outputFolder); + var normalizedTiers = NormalizeTiers(tiers); + + if (normalizedTiers.Length == 0) + return BuildResult(validFolders, materials, normalizedOutputFolder, normalizedTiers, false, "No NBShader feature tiers were selected."); + + if (materials.Length == 0) + return BuildResult(validFolders, materials, normalizedOutputFolder, normalizedTiers, false, "No NBShader materials were found in the selected folders."); + + string errorMessage; + if (!EnsureOutputFolder(normalizedOutputFolder, out errorMessage)) + return BuildResult(validFolders, materials, normalizedOutputFolder, normalizedTiers, false, errorMessage); + + return BuildResult(validFolders, materials, normalizedOutputFolder, normalizedTiers, true); + } + + public static Material[] CollectMaterials(IEnumerable searchFolders) + { + var folders = GetValidSearchFolders(searchFolders); + return CollectMaterialsInValidFolders(folders); + } + + private static Material[] CollectMaterialsInValidFolders(string[] folders) + { + if (folders.Length == 0) + return new Material[0]; + + var guids = AssetDatabase.FindAssets("t:Material", folders); + var result = new List(); + var seen = new HashSet(StringComparer.Ordinal); + for (var i = 0; i < guids.Length; i++) + { + var path = AssetDatabase.GUIDToAssetPath(guids[i]); + if (string.IsNullOrEmpty(path) || !seen.Add(path)) + continue; + + var material = AssetDatabase.LoadAssetAtPath(path); + if (NBShaderMaterialIntentResolver.IsNBShaderMaterial(material)) + result.Add(material); + } + + return result.ToArray(); + } + + public static string[] GetValidSearchFolders(IEnumerable searchFolders) + { + if (searchFolders == null) + return new string[0]; + + var result = new List(); + var seen = new HashSet(StringComparer.Ordinal); + foreach (var searchFolder in searchFolders) + { + var path = NormalizeAssetPath(searchFolder); + if (string.IsNullOrEmpty(path) || !AssetDatabase.IsValidFolder(path) || !seen.Add(path)) + continue; + + result.Add(path); + } + + return result.ToArray(); + } + + internal static string NormalizeAssetPath(string path) + { + if (string.IsNullOrEmpty(path)) + return string.Empty; + + path = path.Replace('\\', '/').Trim(); + if (path.StartsWith("Assets", StringComparison.Ordinal) || + path.StartsWith("Packages", StringComparison.Ordinal)) + { + return path.TrimEnd('/'); + } + + var projectRoot = Path.GetFullPath(Path.Combine(Application.dataPath, "..")).Replace('\\', '/').TrimEnd('/'); + var fullPath = Path.GetFullPath(path).Replace('\\', '/').TrimEnd('/'); + if (fullPath.StartsWith(projectRoot + "/", StringComparison.OrdinalIgnoreCase)) + return fullPath.Substring(projectRoot.Length + 1); + + return string.Empty; + } + + internal static string ToAbsolutePath(string assetPath) + { + assetPath = NormalizeAssetPath(assetPath); + var projectRoot = Path.GetFullPath(Path.Combine(Application.dataPath, "..")).Replace('\\', '/').TrimEnd('/'); + if (string.IsNullOrEmpty(assetPath)) + return projectRoot; + + return Path.Combine(projectRoot, assetPath).Replace('\\', '/'); + } + + public static string GetOutputPath(string outputFolder, NBShaderFeatureTier tier) + { + outputFolder = NormalizeOutputFolder(outputFolder); + if (string.IsNullOrEmpty(outputFolder)) + outputFolder = DefaultOutputFolder; + return outputFolder.TrimEnd('/') + "/NBShader_" + tier + ".shadervariants"; + } + + private static NBShaderVariantCollectionBuildResult BuildResult( + string[] validFolders, + Material[] materials, + string outputFolder, + NBShaderFeatureTier[] tiers, + bool writeAssets, + string errorMessage = null) + { + if (tiers == null) + tiers = CloneDefaultTiers(); + + var tierResults = new NBShaderVariantCollectionTierResult[tiers.Length]; + for (var i = 0; i < tiers.Length; i++) + { + var tier = tiers[i]; + var buildInfo = NBShaderFeatureLevelEditorAPI.GetBuildInfo( + tier, + materials, + NBShaderBuildInfoMode.ExactMaterialVariants); + var variants = BuildSvcVariants(buildInfo); + var path = GetOutputPath(outputFolder, tier); + var generated = false; + string tierError = null; + + if (writeAssets) + generated = WriteCollection(path, variants, out tierError); + + tierResults[i] = new NBShaderVariantCollectionTierResult( + tier, + buildInfo != null ? buildInfo.materials.Length : 0, + buildInfo != null ? buildInfo.includedPassNames.Length : 0, + variants.Length, + path, + generated, + tierError); + } + + return new NBShaderVariantCollectionBuildResult( + validFolders, + materials, + outputFolder, + tierResults, + errorMessage); + } + + private static SvcVariant[] BuildSvcVariants(NBShaderBuildInfoSet buildInfo) + { + if (buildInfo == null) + return new SvcVariant[0]; + + var result = new List(); + var seen = new HashSet(StringComparer.Ordinal); + var variants = buildInfo.variants; + for (var i = 0; i < variants.Length; i++) + { + var variant = variants[i]; + if (variant == null || variant.shader == null) + continue; + + var keywords = variant.keywords; + var key = variant.shader.name + "|" + variant.passType + "|" + string.Join(";", keywords); + if (!seen.Add(key)) + continue; + + result.Add(new SvcVariant(variant.shader, variant.passType, keywords)); + } + + return result.ToArray(); + } + + private static bool WriteCollection(string path, SvcVariant[] variants, out string errorMessage) + { + errorMessage = null; + + var existing = AssetDatabase.LoadAssetAtPath(path); + var collection = existing as ShaderVariantCollection; + if (existing != null && collection == null) + { + errorMessage = "Output path already exists and is not a ShaderVariantCollection:\n" + path; + return false; + } + + if (collection == null) + { + collection = new ShaderVariantCollection(); + AssetDatabase.CreateAsset(collection, path); + } + else + { + collection.Clear(); + } + + for (var i = 0; i < variants.Length; i++) + { + var variant = variants[i]; + try + { + collection.Add(new ShaderVariantCollection.ShaderVariant( + variant.shader, + variant.passType, + variant.keywords)); + } + catch (Exception ex) + { + Debug.LogWarning("Failed to add NBShader SVC variant: " + ex.Message); + } + } + + EditorUtility.SetDirty(collection); + AssetDatabase.SaveAssetIfDirty(collection); + return true; + } + + private static bool EnsureOutputFolder(string outputFolder, out string errorMessage) + { + errorMessage = null; + if (string.IsNullOrEmpty(outputFolder)) + { + errorMessage = "Output folder is empty."; + return false; + } + + if (AssetDatabase.IsValidFolder(outputFolder)) + return true; + + if (!outputFolder.StartsWith("Assets/", StringComparison.Ordinal) && + !string.Equals(outputFolder, "Assets", StringComparison.Ordinal)) + { + errorMessage = "Output folder must already exist unless it is under Assets:\n" + outputFolder; + return false; + } + + var parts = outputFolder.Split('/'); + var current = parts[0]; + for (var i = 1; i < parts.Length; i++) + { + var next = current + "/" + parts[i]; + if (!AssetDatabase.IsValidFolder(next)) + AssetDatabase.CreateFolder(current, parts[i]); + current = next; + } + + if (AssetDatabase.IsValidFolder(outputFolder)) + return true; + + errorMessage = "Could not create output folder:\n" + outputFolder; + return false; + } + + private static string NormalizeOutputFolder(string outputFolder) + { + if (string.IsNullOrEmpty(outputFolder)) + return DefaultOutputFolder; + + return NormalizeAssetPath(outputFolder); + } + + private static NBShaderFeatureTier[] NormalizeTiers(IEnumerable tiers) + { + if (tiers == null) + return CloneDefaultTiers(); + + var selected = new HashSet(); + foreach (var tier in tiers) + { + if (IsValidTier(tier)) + selected.Add(tier); + } + + var result = new List(); + for (var i = 0; i < Tiers.Length; i++) + { + var tier = Tiers[i]; + if (selected.Contains(tier)) + result.Add(tier); + } + + return result.ToArray(); + } + + private static bool IsValidTier(NBShaderFeatureTier tier) + { + return tier == NBShaderFeatureTier.Low || + tier == NBShaderFeatureTier.Medium || + tier == NBShaderFeatureTier.High || + tier == NBShaderFeatureTier.Ultra; + } + + private static NBShaderFeatureTier[] CloneDefaultTiers() + { + return (NBShaderFeatureTier[])Tiers.Clone(); + } + + private sealed class SvcVariant + { + public readonly Shader shader; + public readonly PassType passType; + public readonly string[] keywords; + + public SvcVariant(Shader shader, PassType passType, string[] keywords) + { + this.shader = shader; + this.passType = passType; + this.keywords = keywords != null ? (string[])keywords.Clone() : new string[0]; + } + } + } + + public sealed class NBShaderVariantCollectionBuildResult + { + private readonly string[] m_ValidSearchFolders; + private readonly Material[] m_Materials; + private readonly NBShaderVariantCollectionTierResult[] m_Tiers; + + public readonly string outputFolder; + public readonly string errorMessage; + + public string[] validSearchFolders { get { return (string[])m_ValidSearchFolders.Clone(); } } + public Material[] materials { get { return (Material[])m_Materials.Clone(); } } + public NBShaderVariantCollectionTierResult[] tiers { get { return (NBShaderVariantCollectionTierResult[])m_Tiers.Clone(); } } + public int materialCount { get { return m_Materials.Length; } } + public int validSearchFolderCount { get { return m_ValidSearchFolders.Length; } } + public int generatedCount { get { return CountGenerated(m_Tiers); } } + public bool hasError { get { return !string.IsNullOrEmpty(firstErrorMessage); } } + public bool hasTierError { get { return HasTierError(m_Tiers); } } + public bool allTiersGenerated { get { return m_Tiers.Length > 0 && generatedCount == m_Tiers.Length; } } + public bool succeeded { get { return !hasError && allTiersGenerated; } } + public string firstErrorMessage { get { return GetFirstErrorMessage(errorMessage, m_Tiers); } } + + public NBShaderVariantCollectionBuildResult( + string[] validSearchFolders, + Material[] materials, + string outputFolder, + NBShaderVariantCollectionTierResult[] tiers, + string errorMessage) + { + m_ValidSearchFolders = validSearchFolders != null ? (string[])validSearchFolders.Clone() : new string[0]; + m_Materials = materials != null ? (Material[])materials.Clone() : new Material[0]; + this.outputFolder = outputFolder; + m_Tiers = tiers != null ? (NBShaderVariantCollectionTierResult[])tiers.Clone() : new NBShaderVariantCollectionTierResult[0]; + this.errorMessage = errorMessage; + } + + private static int CountGenerated(NBShaderVariantCollectionTierResult[] tiers) + { + if (tiers == null || tiers.Length == 0) + return 0; + + var count = 0; + for (var i = 0; i < tiers.Length; i++) + { + var tier = tiers[i]; + if (tier != null && tier.generated) + count++; + } + + return count; + } + + private static bool HasTierError(NBShaderVariantCollectionTierResult[] tiers) + { + if (tiers == null || tiers.Length == 0) + return false; + + for (var i = 0; i < tiers.Length; i++) + { + var tier = tiers[i]; + if (tier != null && tier.hasError) + return true; + } + + return false; + } + + private static string GetFirstErrorMessage(string resultError, NBShaderVariantCollectionTierResult[] tiers) + { + if (!string.IsNullOrEmpty(resultError)) + return resultError; + + if (tiers == null || tiers.Length == 0) + return null; + + for (var i = 0; i < tiers.Length; i++) + { + var tier = tiers[i]; + if (tier != null && tier.hasError) + return tier.errorMessage; + } + + return null; + } + } + + public sealed class NBShaderVariantCollectionTierResult + { + public readonly NBShaderFeatureTier tier; + public readonly int materialCount; + public readonly int passCount; + public readonly int variantCount; + public readonly string outputAssetPath; + public readonly bool generated; + public readonly string errorMessage; + + public bool hasError { get { return !string.IsNullOrEmpty(errorMessage); } } + + public NBShaderVariantCollectionTierResult( + NBShaderFeatureTier tier, + int materialCount, + int passCount, + int variantCount, + string outputAssetPath, + bool generated, + string errorMessage) + { + this.tier = tier; + this.materialCount = materialCount; + this.passCount = passCount; + this.variantCount = variantCount; + this.outputAssetPath = outputAssetPath; + this.generated = generated; + this.errorMessage = errorMessage; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantCollectionBuilder.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantCollectionBuilder.cs.meta new file mode 100644 index 00000000..456a5b80 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantCollectionBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f15d05bf7f574642927c7aed8465cff2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantStripper.cs b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantStripper.cs new file mode 100644 index 00000000..c8d2f5c0 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantStripper.cs @@ -0,0 +1,114 @@ +using System.Collections.Generic; +using NBShader; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +using UnityEditor.Rendering; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NBShaders2.Editor.FeatureLevel +{ + public sealed class NBShaderVariantStripper : IPreprocessShaders, IPreprocessBuildWithReport + { + private static bool s_MissingExplicitTierWarningLogged; + + public int callbackOrder { get { return 0; } } + + public void OnPreprocessBuild(BuildReport report) + { + ResetMissingExplicitTierWarning(); + } + + public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList data) + { + if (shader == null || shader.name != NBShaderFeatureLevelCatalog.ShaderName || data == null || data.Count == 0) + return; + + NBShaderFeatureTier tier; + if (!NBShaderFeatureLevelBuildStripOverride.TryGetCurrentTier(out tier)) + LogMissingExplicitTierWarning(); + + var projectSettings = NBShaderFeatureLevelProjectSettings.instance; + HashSet allowedKeywords = projectSettings.GetAllowedKeywordSetForBuildInfoNoSave(tier); + HashSet allowedPassFeatures = projectSettings.GetAllowedPassFeatureSetForBuildInfoNoSave(tier); + + if (IsDisallowedManagedPass(snippet, allowedPassFeatures)) + { + data.Clear(); + return; + } + + for (var i = data.Count - 1; i >= 0; i--) + { + if (ContainsDisallowedManagedKeyword(shader, data[i], allowedKeywords)) + data.RemoveAt(i); + } + } + + private static void LogMissingExplicitTierWarning() + { + if (s_MissingExplicitTierWarningLogged) + return; + + s_MissingExplicitTierWarningLogged = true; + Debug.LogWarning( + "NBShader2 build stripping tier was not specified. Defaulting to Ultra. " + + "Wrap BuildPipeline.BuildPlayer or BuildPipeline.BuildAssetBundles in " + + "NBShaderFeatureLevelEditorAPI.OverrideBuildStripExplicitTier(tier) to build lower-tier NBShader variants intentionally."); + } + + internal static void ResetMissingExplicitTierWarning() + { + s_MissingExplicitTierWarningLogged = false; + } + + private static bool IsDisallowedManagedPass(ShaderSnippetData snippet, HashSet allowedPassFeatures) + { + if (allowedPassFeatures == null) + return false; + + string passFeatureId; + if (!TryResolveManagedPassFeature(snippet, out passFeatureId)) + return false; + + return !allowedPassFeatures.Contains(passFeatureId); + } + + private static bool TryResolveManagedPassFeature(ShaderSnippetData snippet, out string passFeatureId) + { + if (!string.IsNullOrEmpty(snippet.passName) && + NBShaderFeatureLevelCatalog.TryGetManagedPassFeatureByPassName(snippet.passName, out passFeatureId)) + { + return true; + } + + switch (snippet.passType) + { + case PassType.ScriptableRenderPipelineDefaultUnlit: + passFeatureId = NBShaderPassFeatureCatalog.BackFirstPassId; + return true; + case PassType.ShadowCaster: + passFeatureId = NBShaderPassFeatureCatalog.ShadowCasterPassId; + return true; + default: + passFeatureId = string.Empty; + return false; + } + } + + private static bool ContainsDisallowedManagedKeyword(Shader shader, ShaderCompilerData compilerData, HashSet allowed) + { + var keywords = compilerData.shaderKeywordSet.GetShaderKeywords(); + for (var i = 0; i < keywords.Length; i++) + { + var keywordName = keywords[i].name; + if (!NBShaderFeatureLevelCatalog.IsManagedKeyword(keywordName)) + continue; + + if (allowed != null && !allowed.Contains(keywordName)) + return true; + } + return false; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantStripper.cs.meta b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantStripper.cs.meta new file mode 100644 index 00000000..20f4fb77 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/FeatureLevel/NBShaderVariantStripper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b503214133aa446e59281f9583f6a285 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/Localization.meta b/Packages/NB_FX/NBShaders2/Editor/Localization.meta new file mode 100644 index 00000000..d8b157bc --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/Localization.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 624337c343f09c34091f162af2089afe +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.cs b/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.cs new file mode 100644 index 00000000..145c2307 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.cs @@ -0,0 +1,80 @@ +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + [InitializeOnLoad] + internal static class NBShaderInspectorLocalization + { + internal const string TableName = "NBShader"; + + private const string CsvAssetPath = "Packages/com.xuanxuan.nb.fx/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv"; + + static NBShaderInspectorLocalization() + { + RegisterTable(); + } + + public static string CurrentLanguage + { + get + { + RegisterTable(); + return ShaderGUILocalization.GetCurrentLanguage(TableName); + } + } + + public static GUIContent MakeContent(string labelKey, string labelFallback, string tooltipKey = null, string tooltipFallback = "") + { + RegisterTable(); + return ShaderGUILocalization.MakeContent(TableName, labelKey, labelFallback, tooltipKey, tooltipFallback); + } + + public static GUIContent MakeInspectorContent(string key, string fallback, string tip = "") + { + RegisterTable(); + return ShaderGUILocalization.MakeInspectorContent(TableName, key, fallback, tip); + } + + public static string GetInspectorText(string key, string fallback = "") + { + RegisterTable(); + return ShaderGUILocalization.GetInspectorText(TableName, key, fallback); + } + + public static string[] GetInspectorOptions(string key, string[] fallback) + { + RegisterTable(); + return ShaderGUILocalization.GetInspectorOptions(TableName, key, fallback); + } + + public static string[] GetOptions(string keyPrefix, string[] fallback) + { + RegisterTable(); + return ShaderGUILocalization.GetOptions(TableName, keyPrefix, fallback); + } + + public static string Get(string key, string fallback = "") + { + RegisterTable(); + return ShaderGUILocalization.Get(TableName, key, fallback); + } + + public static string GetTooltip(string labelKey, string tooltipKey = null, string fallback = "") + { + RegisterTable(); + return ShaderGUILocalization.GetTooltip(TableName, labelKey, tooltipKey, fallback); + } + + public static void Reload() + { + RegisterTable(); + ShaderGUILocalization.Reload(TableName); + } + + private static void RegisterTable() + { + ShaderGUILocalization.RegisterCsv(TableName, CsvAssetPath); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.cs.meta b/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.cs.meta new file mode 100644 index 00000000..38aa244f --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8dd81afc56b7652468af814441ee910f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv b/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv new file mode 100644 index 00000000..9d5bc8a0 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv @@ -0,0 +1,805 @@ +key,zh-CN,en-US,zh-CN-tip,en-US-tip +inspector.block.mode.label,模式设置,Mode,各种基础模式设置,Mode and source setup +inspector.block.base.label,基本全局功能,Base,全局控制功能,Base global controls +inspector.block.maintex.label,主贴图功能,Main Texture,主贴图以及主颜色相关功能,Main texture and base color controls +inspector.block.light.label,光照功能,Lighting,法线、MatCap 和光照模式相关功能,Lighting normal and material response controls +inspector.block.feature.label,特别功能,Feature,遮罩、扭曲、溶解等特效功能,Effect feature controls +inspector.block.ta.label,TA调试,TA Debug,技术美术调试和辅助功能,Technical art debug and helper controls +inspector.common.tilling.label,Tilling,Tilling,, +inspector.common.offset.label,Offset,Offset,, +inspector.common.none,None,None,, +inspector.mode.meshSource.label,Mesh来源模式,Mesh Source Mode,Mesh来源模式和当前的对象类型一致,Matches the current object type +inspector.mode.meshSource.option.0,粒子系统,Particle System,, +inspector.mode.meshSource.option.1,模型(非粒子发射),Mesh,, +inspector.mode.meshSource.option.2,2D RawImage,2D RawImage,, +inspector.mode.meshSource.option.3,2D 精灵,2D Sprite,, +inspector.mode.meshSource.option.4,2D 材质贴图,2D Material Texture,, +inspector.mode.meshSource.option.5,2D UIParticle,2D UIParticle,, +inspector.mode.transparent.label,透明模式,Transparent Mode,透明模式,Controls opaque transparent and cutoff rendering +inspector.mode.transparent.option.0,不透明Opaque,Opaque,, +inspector.mode.transparent.option.1,半透明Transparent,Transparent,, +inspector.mode.transparent.option.2,不透明裁剪CutOff,CutOff,, +inspector.mode.cutoff.label,裁剪位置,Cutoff,0为完全不裁剪,1为完全裁剪,0 keeps everything and 1 clips everything +inspector.mode.blend.label,混合模式,Blend Mode,, +inspector.mode.blend.option.0,透明度混合AlphaBlend,Alpha Blend,, +inspector.mode.blend.option.1,预乘PreMultiply,Premultiply,, +inspector.mode.blend.option.2,叠加Additive,Additive,, +inspector.mode.blend.option.3,正片叠底Multiply,Multiply,, +inspector.mode.additiveToPremultiply.label,叠加到预乘混合,Additive To Premultiply,0为叠加混合,1为预乘混合,0 is additive and 1 is premultiply +inspector.base.colorIntensity.label,整体颜色强度,Base Color Intensity,, +inspector.base.alphaAll.label,整体透明度,Overall Alpha,, +inspector.base.colorAdjustment.label,颜色调整,Color Adjustment,, +inspector.base.colorAdjustment.onlyMainTex.label,颜色调整仅影响主贴图,Color Adjustment Only Affects Main Texture,, +inspector.base.hueShift.label,色相偏移,Hue Shift,, +inspector.base.hueShift.value.label,色相,Hue,, +inspector.base.hueShift.customData.label,色相自定义曲线,Hue Custom Data,, +inspector.base.saturability.label,饱和度,Saturation,, +inspector.base.saturability.value.label,饱和度,Saturation,, +inspector.base.saturability.customData.label,饱和度强度自定义曲线,Saturation Strength Custom Data,, +inspector.base.contrast.label,对比度,Contrast,, +inspector.base.contrast.mid.label,对比度中值颜色,Contrast Mid Color,, +inspector.base.contrast.value.label,对比度,Contrast,, +inspector.base.contrast.customData.label,对比度自定义曲线,Contrast Custom Data,, +inspector.base.colorRefine.label,颜色修正,Color Refine,, +inspector.base.colorRefine.a.label,A:主颜色相乘,A Main Color Multiply,, +inspector.base.colorRefine.bPower.label,B:主颜色Power,B Main Color Power,, +inspector.base.colorRefine.bMultiply.label,B:主颜色Power后相乘,B After Power Multiply,, +inspector.base.colorRefine.lerp.label,A/B线性差值,A/B Lerp,, +inspector.base.colorMultiAlpha.label,颜色乘透明度(改善锯齿),Color Multiply Alpha,, +inspector.base.ztest.label,深度测试,ZTest,, +inspector.base.ztest.option.0,关闭(Disabled),Disabled,, +inspector.base.ztest.option.1,永不通过(Never),Never,, +inspector.base.ztest.option.2,小于(Less),Less,, +inspector.base.ztest.option.3,等于(Equal),Equal,, +inspector.base.ztest.option.4,小于等于(LessEqual),LessEqual,, +inspector.base.ztest.option.5,大于(Greater),Greater,, +inspector.base.ztest.option.6,不等于(NotEqual),NotEqual,, +inspector.base.ztest.option.7,大于等于(GreaterEqual),GreaterEqual,, +inspector.base.ztest.option.8,始终通过(Always),Always,, +inspector.base.cull.label,渲染面向,Cull,, +inspector.base.cull.option.0,双面(Both),Both,, +inspector.base.cull.option.1,背面(Back),Back,, +inspector.base.cull.option.2,正面(Front),Front,, +inspector.base.backFirstPass.label,预渲染反面,Back First Pass,, +inspector.base.forceZWrite.label,深度写入强制控制,Force ZWrite,, +inspector.base.forceZWrite.option.0,默认,Default,, +inspector.base.forceZWrite.option.1,强制开启,Force On,, +inspector.base.forceZWrite.option.2,强制关闭,Force Off,, +inspector.base.affectsShadows.label,投射阴影,Affects Shadows,, +inspector.base.transparentShadowDither.label,半透明 Dither 阴影,Transparent Dither Shadows,, +inspector.base.backColor.label,背面颜色,Back Color,, +inspector.base.backColor.color.label,背面颜色,Back Color,, +inspector.base.distanceFade.label,近距离透明,Distance Fade,, +inspector.base.distanceFade.range.label,透明过度范围,Fade Range,, +inspector.base.softParticles.label,软粒子,Soft Particles,, +inspector.base.softParticles.range.label,远近裁剪面,Near/Far Fade,, +inspector.base.stencilWithoutPlayer.label,剔除主角色,Stencil Without Player,, +inspector.base.ignoreVertexColor.label,忽略顶点色,Ignore Vertex Color,, +inspector.base.fogIntensity.label,雾影响强度,Fog Intensity,, +inspector.maintex.basemap.label,主贴图,Main Texture,, +inspector.maintex.basemap.related.label,主贴图相关功能,Main Texture Related,, +inspector.maintex.graphic.message,当前模式使用 Graphic 贴图。仅颜色和 ST 可编辑。,Current mode uses Graphic texture. Only color and ST remain editable.,, +inspector.maintex.uicolor.label,贴图颜色叠加,Graphic Color,, +inspector.maintex.alphaChannel.label,主贴图透明度通道,Alpha Channel,, +inspector.maintex.wrap.label,主贴图循环模式,Main Texture Wrap,, +inspector.maintex.uvmode.label,主贴图UV来源,Main Texture UV Source,, +inspector.maintex.customdata.offsetx.label,主贴图X轴偏移自定义曲线,Main Texture Offset X Custom Data,, +inspector.maintex.customdata.offsety.label,主贴图Y轴偏移自定义曲线,Main Texture Offset Y Custom Data,, +inspector.maintex.offsetspeed.label,偏移速度,Offset Speed,, +inspector.maintex.rotation.label,主贴图旋转,Rotation,, +inspector.maintex.rotationspeed.label,主贴图旋转速度,Rotation Speed,, +inspector.maintex.distortionIntensity.label,主贴图扭曲强度控制,Main Texture Distortion,, +inspector.maintex.pnoiseBlend.label,主贴图程序噪波混合,Main Texture Program Noise Blend,, +inspector.maintex.mixedMeshSource.message,混合的 Mesh 来源模式会按材质状态显示对应贴图控件。,Mixed mesh-source modes will show the matching texture controls per material state.,, +inspector.light.mode.label,光照类型,Light Mode,, +inspector.light.mode.option.0,默认无光(Unlit),Unlit,, +inspector.light.mode.option.1,简单光照(BlinnPhong),BlinnPhong,, +inspector.light.mode.option.2,简单光照通透(HalfLambert),HalfLambert,, +inspector.light.mode.option.3,高级光照(PBR),PBR,, +inspector.light.mode.option.4,六路光照(SixWay),SixWay,, +inspector.light.specular.toggle.label,高光开关,Specular,, +inspector.light.specular.color.label,高光颜色,Specular Color,, +inspector.light.specular.smoothness.label,光滑度,Smoothness,, +inspector.light.pbr.metallic.label,金属度,Metallic,, +inspector.light.pbr.smoothness.label,光滑度,Smoothness,, +inspector.light.bump.toggle.label,法线贴图开关,Normal Map,, +inspector.light.bump.texture.label,法线贴图,Normal Map,, +inspector.light.bump.related.label,法线贴图相关功能,Normal Map Related,, +inspector.light.bump.wrap.label,法线贴图循环模式,Normal Map Wrap,, +inspector.light.bump.uvmode.label,法线贴图UV来源,Normal Map UV Source,, +inspector.light.bump.maskMode.label,法线贴图多通道模式,Normal Map Multi Channel,, +inspector.light.bump.scale.label,法线强度,Normal Strength,, +inspector.light.matcap.toggle.label,MatCap模拟材质,MatCap,, +inspector.light.matcap.texture.label,MatCap图,MatCap Texture,, +inspector.light.matcap.blend.label,MatCap相加到相乘过渡,Add/Multiply Blend,, +inspector.light.sixway.positive.label,六路正方向图(P),SixWay Positive,, +inspector.light.sixway.negative.label,六路反方向图(N),SixWay Negative,, +inspector.light.sixway.absorption.toggle.label,光照颜色吸收,Light Color Absorption,, +inspector.light.sixway.absorption.strength.label,六路吸收强度,Absorption Strength,, +inspector.light.sixway.ramp.label,六路自发光Ramp,SixWay Emission Ramp,, +inspector.light.sixway.emissionPow.label,六路自发光Pow,SixWay Emission Pow,, +inspector.light.sixway.color.label,六路自发光颜色,SixWay Emission Color,, +inspector.protocol.colorChannel.option.0,R,R,, +inspector.protocol.colorChannel.option.1,G,G,, +inspector.protocol.colorChannel.option.2,B,B,, +inspector.protocol.colorChannel.option.3,A,A,, +inspector.protocol.customData.option.0,**不使用**,Off,, +inspector.protocol.customData.option.1,CustomData1_X,CustomData1.x,, +inspector.protocol.customData.option.2,CustomData1_Y,CustomData1.y,, +inspector.protocol.customData.option.3,CustomData1_Z,CustomData1.z,, +inspector.protocol.customData.option.4,CustomData1_W,CustomData1.w,, +inspector.protocol.customData.option.5,CustomData2_X,CustomData2.x,, +inspector.protocol.customData.option.6,CustomData2_Y,CustomData2.y,, +inspector.protocol.customData.option.7,CustomData2_Z,CustomData2.z,, +inspector.protocol.customData.option.8,CustomData2_W,CustomData2.w,, +inspector.protocol.wrapMode.option.0,Repeat,Repeat,, +inspector.protocol.wrapMode.option.1,Clamp,Clamp,, +inspector.protocol.wrapMode.option.2,RepeatX_ClampY,RepeatX_ClampY,, +inspector.protocol.wrapMode.option.3,ClampX_RepeatY,ClampX_RepeatY,, +inspector.protocol.pnoise.opacity.label,程序噪波混合强度,Program Noise Blend Opacity,, +inspector.protocol.pnoiseBlend.option.0,不使用,Not Used,, +inspector.protocol.pnoiseBlend.option.1,Multiply,Multiply,, +inspector.protocol.pnoiseBlend.option.2,Min,Min,, +inspector.protocol.pnoiseBlend.option.3,HardLight,HardLight,, +inspector.protocol.uv.twirl.label,旋转扭曲,Twirl,, +inspector.protocol.uv.twirlCenter.label,旋转扭曲中心,Twirl Center,, +inspector.protocol.uv.twirlStrength.label,旋转扭曲强度,Twirl Strength,, +inspector.protocol.uv.polar.label,极坐标,Polar Coordinates,, +inspector.protocol.uv.polarCenter.label,极坐标中心,Polar Center,, +inspector.protocol.uv.polarStrength.label,极坐标强度,Polar Strength,, +inspector.protocol.uv.cylinderRotate.label,圆柱坐标旋转,Cylinder Rotation,, +inspector.protocol.uv.cylinderOffset.label,圆柱坐标偏移,Cylinder Offset,, +inspector.protocol.uv.coordinatePlane.label,坐标平面,Coordinate Plane,, +inspector.protocol.uv.sharedMaterial.message,以下设置材质内通用:,The following settings are shared in the material:,, +inspector.protocol.uv.cylinderWarning.message,圆柱模式消耗比较大,慎用,Cylinder mode is expensive. Use it carefully.,, +inspector.protocol.uv.mode.option.0,默认UV通道,Default UV Channel,, +inspector.protocol.uv.mode.option.1,特殊UV通道,Special UV Channel,, +inspector.protocol.uv.mode.option.2,极坐标|旋转,Polar/Twirl,, +inspector.protocol.uv.mode.option.3,圆柱无缝,Cylinder Seamless,, +inspector.protocol.uv.mode.option.4,主贴图,Main Texture,, +inspector.protocol.uv.mode.option.5,屏幕UV,Screen UV,, +inspector.protocol.uv.mode.option.6,世界坐标,World Space,, +inspector.protocol.uv.mode.option.7,局部本地坐标,Object Space,, +inspector.protocol.uv.mode.option.8,公共UV,Shared UV,, +inspector.protocol.uv.positionPlane.option.0,xy平面,XY Plane,, +inspector.protocol.uv.positionPlane.option.1,xz平面,XZ Plane,, +inspector.protocol.uv.positionPlane.option.2,yz平面,YZ Plane,, +inspector.protocol.uv.specialChannel.label,特殊UV通道选择,Special UV Channel,, +inspector.protocol.uv.specialChannel.option.0,UV2_Texcoord1,UV2_Texcoord1,, +inspector.protocol.uv.specialChannel.option.1,UV3_Texcoord2,UV3_Texcoord2,, +inspector.ta.zoffset.label,深度偏移,Z Offset,, +inspector.ta.overrideZ.label,Override Z,Override Z,, +inspector.ta.renderQueue.label,渲染队列偏移,Queue Bias,, +inspector.ta.customStencil.label,模板手动调试开关,Custom Stencil Test,, +inspector.ta.keywords.label,已开启Keyword:,Enabled Keywords,, +inspector.ta.keywords.list.label,已开启Keyword:,Enabled Keywords,, +inspector.ta.property._offsetFactor.label,OffsetFactor,Offset Factor,, +inspector.ta.property._offsetUnits.label,Offset单位,Offset Units,, +inspector.ta.property._OverrideZValue.label,Override Z Value,Override Z Value,, +inspector.ta.property._ColorMask.label,RGBA Mask,RGBA Mask,控制最终写入 RenderTarget 的颜色通道,Controls final RenderTarget color channel writes +inspector.ta.colorMask.option.0,R,R,, +inspector.ta.colorMask.option.1,G,G,, +inspector.ta.colorMask.option.2,B,B,, +inspector.ta.colorMask.option.3,A,A,, +inspector.ta.property._StencilKeyIndex.label,Stencil配置索引,Stencil Config Index,, +inspector.ta.property._Stencil.label,模板值,Stencil Value,, +inspector.ta.property._StencilComp.label,模板比较方式,Stencil Compare,, +inspector.ta.property._StencilOp.label,模板处理方式,Stencil Operation,, +inspector.ta.property._StencilFail.label,模板失败处理方式,Stencil Fail,, +inspector.ta.property._StencilZFail.label,模板深度失败处理方式,Stencil ZFail,, +inspector.ta.property._StencilReadMask.label,模板读取掩码,Stencil Read Mask,, +inspector.ta.property._StencilWriteMask.label,模板写入掩码,Stencil Write Mask,, +inspector.vertexStreams.title.label,顶点流统计,Particle Vertex Streams,The vertex streams needed for this Material to function properly.,The vertex streams needed for this Material to function properly. +inspector.vertexStreams.mismatch,下面的粒子系统Renderer顶点流不正确:,Particle renderers with mismatched vertex streams:,, +inspector.vertexStreams.trailMismatch,下面的粒子系统Renderer拖尾顶点流不正确:,Particle trail renderers with mismatched vertex streams:,, +inspector.vertexStreams.applyTrail.button,使粒子拖尾与材质顶点流相同,Apply Trail Vertex Streams,Apply the trail vertex stream layout to all Particle Systems using this material,Apply the trail vertex stream layout to all Particle Systems using this material +inspector.vertexStreams.apply.button,使粒子与材质顶点流相同,Apply Vertex Streams,Apply the vertex stream layout to all Particle Systems using this material,Apply the vertex stream layout to all Particle Systems using this material +inspector.vertexStreams.apply.undo,Apply custom vertex streams from material,Apply custom vertex streams from material,, +inspector.feature.popup._ScreenDistortModeToggle.option.0,不扰动屏幕,No Screen Distort,, +inspector.feature.popup._ScreenDistortModeToggle.option.1,全部扰动(后处理扰动),Deferred Distort,, +inspector.feature.popup._ScreenDistortModeToggle.option.2,仅影响场景(半透明前扰动),Camera Opaque Distort,, +inspector.feature.screenDistort.missingNbPostProcess.message,屏幕扭曲需要当前 URP Pipeline Asset 的任意 RendererData 中包含已启用的 NB 后处理 Feature。,Screen Distort requires at least one RendererData in the current URP Pipeline Asset to include an active NB Post Process Feature.,, +inspector.feature.screenDistort.missingOpaqueTextureCopy.message,Camera Opaque 扭曲需要在当前 URP Pipeline Asset 中开启 Opaque Texture。,Camera Opaque Distort requires Opaque Texture to be enabled on the current URP Pipeline Asset.,, +inspector.feature.screenDistort.pingRendererData.button,定位 Renderer,Ping Renderer,, +inspector.feature.screenDistort.pingPipelineAsset.button,定位 Pipeline Asset,Ping Pipeline Asset,, +inspector.feature.popup._DistortMode.option.0,扰动贴图,FlowMap/RG Texture,, +inspector.feature.popup._DistortMode.option.1,折射,Refraction IOR,, +inspector.feature.popup._ColorBlendAlphaMultiplyMode.option.0,颜色渐变强度,Off,, +inspector.feature.popup._ColorBlendAlphaMultiplyMode.option.1,遮罩(乘以主贴图Alpha),On,, +inspector.feature.popup._RampColorSourceMode.option.0,UV,Gradient,, +inspector.feature.popup._RampColorSourceMode.option.1,映射贴图,Texture,, +inspector.feature.popup._RampColorBlendMode.option.0,相乘Multiply,Add,, +inspector.feature.popup._RampColorBlendMode.option.1,相加Add,Multiply,, +inspector.feature.popup._DissolveRampSourceMode.option.0,渐变控件,Gradient,, +inspector.feature.popup._DissolveRampSourceMode.option.1,Ramp贴图,Texture,, +inspector.feature.popup._DissolveRampColorBlendMode.option.0,线性差值Lerp,Add,, +inspector.feature.popup._DissolveRampColorBlendMode.option.1,相乘Multiply,Multiply,, +inspector.feature.popup._DissolveMaskMode.option.0,过程溶解,Process Dissolve,, +inspector.feature.popup._DissolveMaskMode.option.1,溶解遮罩,Dissolve Mask,, +inspector.feature.popup._FresnelMode.option.0,颜色|边缘光,Color,, +inspector.feature.popup._FresnelMode.option.1,半透明|渐隐,Alpha,, +inspector.feature.popup._VATMode.option.0,Houdini,Houdini,, +inspector.feature.popup._VATMode.option.1,TyFlow,TyFlow,, +inspector.feature.popup._HoudiniVATSubMode.option.0,SoftBody (Deformation),SoftBody (Deformation),, +inspector.feature.popup._HoudiniVATSubMode.option.1,RigidBody (Pieces),RigidBody (Pieces),, +inspector.feature.popup._HoudiniVATSubMode.option.2,Dynamic Remeshing (Lookup),Dynamic Remeshing (Lookup),, +inspector.feature.popup._HoudiniVATSubMode.option.3,Particle Sprites (Billboard),Particle Sprites (Billboard),, +inspector.feature.popup._TyFlowVATSubMode.option.0,Absolute positions,Absolute positions,, +inspector.feature.popup._TyFlowVATSubMode.option.1,Relative offsets,Relative offsets,, +inspector.feature.popup._TyFlowVATSubMode.option.2,Skin (R),Skin (R),, +inspector.feature.popup._TyFlowVATSubMode.option.3,Skin (PR),Skin (PR),, +inspector.feature.popup._TyFlowVATSubMode.option.4,Skin (PRSAVE),Skin (PRSAVE),, +inspector.feature.popup._TyFlowVATSubMode.option.5,Skin (PRSXYZ),Skin (PRSXYZ),, +inspector.feature.popup._MaskMapGradientToggle.option.0,遮罩贴图,Texture,, +inspector.feature.popup._MaskMapGradientToggle.option.1,渐变控件,Gradient,, +inspector.feature.popup._MaskMap2GradientToggle.option.0,遮罩贴图,Texture,, +inspector.feature.popup._MaskMap2GradientToggle.option.1,渐变控件,Gradient,, +inspector.feature.popup._MaskMap3GradientToggle.option.0,遮罩贴图,Texture,, +inspector.feature.popup._MaskMap3GradientToggle.option.1,渐变控件,Gradient,, +inspector.feature.vat.houdiniUnsupportedParticle.message,该 Houdini VAT 类型需要 Mesh 多 UV 数据,不支持 ParticleSystem VertexStream 模式。,This Houdini VAT type requires mesh multi-UV data and does not support ParticleSystem VertexStream mode.,, +inspector.feature.vat.tyflowUnsupportedParticle.message,该 TyFlow VAT 类型需要 Mesh 多 UV 数据,不支持 ParticleSystem VertexStream 模式。,This TyFlow VAT type requires mesh multi-UV data and does not support ParticleSystem VertexStream mode.,, +inspector.feature.vat.tyflowUv2Conflict.message,TyFlow VAT 在粒子模式下使用 UV2 (TEXCOORD0.zw) 作为 vertexIndex / vertexCount。序列帧融帧或特殊 UV (UV2) 会冲突,VAT 优先。,TyFlow VAT uses UV2 (TEXCOORD0.zw) as vertexIndex / vertexCount in ParticleSystem mode. Flipbook blending or Special UV (UV2) conflicts with it; VAT takes priority.,, +inspector.feature.遮罩.label,遮罩,Mask,, +inspector.feature.测试遮罩颜色.label,测试遮罩颜色,Debug Mask Color,, +inspector.feature.遮罩强度.label,遮罩强度,Mask Strength,, +inspector.feature.遮罩整体调整.label,遮罩整体调整,Mask Refine,, +inspector.feature.范围(Pow).label,范围(Pow),Range (Pow),, +inspector.feature.相乘.label,相乘,Multiply,, +inspector.feature.偏移(相加).label,偏移(相加),Offset (Add),, +inspector.feature.遮罩程序噪波混合.label,遮罩程序噪波混合,Mask Program Noise Blend,, +inspector.feature.遮罩模式.label,遮罩模式,Mask Mode,, +inspector.feature.遮罩贴图.label,遮罩贴图,Mask Texture,, +inspector.feature.遮罩通道选择.label,遮罩通道选择,Mask Channel,, +inspector.feature.遮罩渐变.label,遮罩渐变,Mask Gradient,, +inspector.feature.遮罩UV Wrap.label,遮罩循环模式,Mask UV Wrap,, +inspector.feature.遮罩UV来源.label,遮罩UV来源,Mask UV Source,, +inspector.feature.Mask图X轴偏移自定义曲线.label,Mask图X轴偏移自定义曲线,Mask Offset X Custom Data,, +inspector.feature.Mask图Y轴偏移自定义曲线.label,Mask图Y轴偏移自定义曲线,Mask Offset Y Custom Data,, +inspector.feature.遮罩偏移速度.label,遮罩偏移速度,Mask Offset Speed,, +inspector.feature.遮罩旋转.label,遮罩旋转,Mask Rotation,, +inspector.feature.遮罩旋转速度.label,遮罩旋转速度,Mask Rotation Speed,, +inspector.feature.旋转速度.label,旋转速度,Rotation Speed,, +inspector.feature.遮罩扭曲强度.label,遮罩扭曲强度,Mask Distortion Strength,, +inspector.feature.遮罩2.label,遮罩2,Mask 2,, +inspector.feature.遮罩2模式.label,遮罩2模式,Mask 2 Mode,, +inspector.feature.遮罩2贴图.label,遮罩2贴图,Mask 2 Texture,, +inspector.feature.遮罩2通道选择.label,遮罩2通道选择,Mask 2 Channel,, +inspector.feature.遮罩2渐变.label,遮罩2渐变(UV纵向),Mask 2 Gradient,, +inspector.feature.遮罩2UV Wrap.label,遮罩2UV循环模式,Mask 2 UV Wrap,, +inspector.feature.遮罩2UV来源.label,遮罩2UV来源,Mask 2 UV Source,, +inspector.feature.遮罩2旋转.label,遮罩2旋转,Mask 2 Rotation,, +inspector.feature.遮罩2偏移速度.label,遮罩2偏移速度,Mask 2 Offset Speed,, +inspector.feature.遮罩3.label,遮罩3,Mask 3,, +inspector.feature.遮罩3模式.label,遮罩3模式,Mask 3 Mode,, +inspector.feature.遮罩3贴图.label,遮罩3贴图,Mask 3 Texture,, +inspector.feature.遮罩3通道选择.label,遮罩3通道选择,Mask 3 Channel,, +inspector.feature.遮罩3渐变.label,遮罩3渐变(UV横向),Mask 3 Gradient,, +inspector.feature.遮罩3UV Wrap.label,遮罩3UV循环模式,Mask 3 UV Wrap,, +inspector.feature.遮罩3UV来源.label,遮罩3UV来源,Mask 3 UV Source,, +inspector.feature.遮罩3旋转.label,遮罩3旋转,Mask 3 Rotation,, +inspector.feature.遮罩3偏移速度.label,遮罩3偏移速度,Mask 3 Offset Speed,, +inspector.feature.扭曲.label,扭曲,Distort,, +inspector.feature.扭曲强度值测试.label,扭曲强度值测试,Debug Distort Strength,, +inspector.feature.整体扭曲强度.label,整体扭曲强度,Overall Distort Strength,, +inspector.feature.扭曲强度自定义曲线.label,扭曲强度自定义曲线,Distort Strength Custom Data,, +inspector.feature.屏幕扰动模式.label,屏幕扰动模式,Screen Distort Mode,, +inspector.feature.屏幕扭曲强度.label,屏幕扭曲强度,Screen Distort Strength,, +inspector.feature.关闭主材质Pass.label,关闭主材质Pass,Disable Main Material Pass,, +inspector.feature.屏幕扭曲Alpha整体调整.label,屏幕扭曲Alpha整体调整,Screen Distort Alpha Refine,, +inspector.feature.扭曲模式.label,扭曲模式,Distort Mode,, +inspector.feature.扭曲贴图.label,扭曲贴图,Distort Texture,, +inspector.feature.扭曲贴图 Wrap.label,扭曲贴图循环模式,Distort Texture Wrap,, +inspector.feature.扭曲贴图UV来源.label,扭曲贴图UV来源,Distort Texture UV Source,, +inspector.feature.扭曲方向强度.label,扭曲方向强度,Distort Direction Strength,, +inspector.feature.扭曲方向强度X自定义曲线.label,扭曲方向强度X自定义曲线,Distort Direction X Custom Data,, +inspector.feature.扭曲方向强度Y自定义曲线.label,扭曲方向强度Y自定义曲线,Distort Direction Y Custom Data,, +inspector.feature.扭曲旋转.label,扭曲旋转,Distort Rotation,, +inspector.feature.扭曲偏移速度.label,扭曲偏移速度,Distort Offset Speed,, +inspector.feature.0.5为中值,双向扭曲.label,0.5为中值,双向扭曲,0.5 Is Mid Value Bidirectional Distort,, +inspector.feature.折射率.label,折射率,Refraction IOR,, +inspector.feature.扭曲程序噪波混合.label,扭曲程序噪波混合,Distort Program Noise Blend,, +inspector.feature.扭曲遮罩.label,扭曲遮罩,Distort Mask,, +inspector.feature.扭曲遮罩贴图.label,扭曲遮罩贴图,Distort Mask Texture,, +inspector.feature.扭曲遮罩贴图 Wrap.label,扭曲遮罩贴图循环模式,Distort Mask Texture Wrap,, +inspector.feature.扭曲遮罩图通道选择.label,扭曲遮罩图通道选择,Distort Mask Channel,, +inspector.feature.扭曲遮罩贴图UV来源.label,扭曲遮罩贴图UV来源,Distort Mask UV Source,, +inspector.feature.色散.label,色散,Chromatic Aberration,, +inspector.feature.色散强度受扭曲强度影响.label,色散强度受扭曲强度影响,Chromatic Strength Follows Distort Strength,, +inspector.feature.色散强度.label,色散强度,Chromatic Strength,, +inspector.feature.色散强度自定义曲线.label,色散强度自定义曲线,Chromatic Strength Custom Data,, +inspector.feature.流光(颜色相加).label,流光(颜色相加),Emission (Add Color),, +inspector.feature.流光贴图.label,流光贴图,Emission Texture,, +inspector.feature.流光贴图 Wrap.label,流光贴图循环模式,Emission Texture Wrap,, +inspector.feature.流光贴图UV来源.label,流光贴图UV来源,Emission Texture UV Source,, +inspector.feature.流光贴图X轴偏移自定义曲线.label,流光贴图X轴偏移自定义曲线,Emission Offset X Custom Data,, +inspector.feature.流光贴图Y轴偏移自定义曲线.label,流光贴图Y轴偏移自定义曲线,Emission Offset Y Custom Data,, +inspector.feature.流光贴图旋转.label,流光贴图旋转,Emission Texture Rotation,, +inspector.feature.流光贴图偏移速度.label,流光贴图偏移速度,Emission Offset Speed,, +inspector.feature.流光贴图扭曲强度.label,流光贴图扭曲强度,Emission Distortion Strength,, +inspector.feature.流光颜色强度.label,流光颜色强度,Emission Color Intensity,, +inspector.feature.渐变(颜色相乘).label,渐变(颜色相乘),Color Blend (Multiply),, +inspector.feature.颜色渐变贴图.label,颜色渐变贴图,Color Blend Texture,, +inspector.feature.颜色渐变贴图 Wrap.label,颜色渐变贴图循环模式,Color Blend Texture Wrap,, +inspector.feature.颜色渐变贴图UV来源.label,颜色渐变贴图UV来源,Color Blend UV Source,, +inspector.feature.颜色渐变贴图X轴偏移自定义曲线.label,颜色渐变贴图X轴偏移自定义曲线,Color Blend Offset X Custom Data,, +inspector.feature.颜色渐变贴图Y轴偏移自定义曲线.label,颜色渐变贴图Y轴偏移自定义曲线,Color Blend Offset Y Custom Data,, +inspector.feature.颜色渐变贴图旋转.label,颜色渐变贴图旋转,Color Blend Texture Rotation,, +inspector.feature.颜色渐变贴图偏移速度.label,颜色渐变贴图偏移速度,Color Blend Offset Speed,, +inspector.feature.颜色渐变扭曲强度.label,颜色渐变扭曲强度,Color Blend Distortion Strength,, +inspector.feature.颜色渐变图Alpha作用.label,颜色渐变图Alpha作用,Color Blend Alpha Mode,, +inspector.feature.颜色渐变图Alpha强度.label,颜色渐变图Alpha强度,Color Blend Alpha Strength,, +inspector.feature.颜色映射(Ramp).label,颜色映射(Ramp),Ramp Color,, +inspector.feature.Ramp来源模式.label,Ramp来源模式,Ramp Source Mode,, +inspector.feature.颜色映射黑白图.label,颜色映射黑白图,Ramp Mask Texture,, +inspector.feature.颜色映射黑白图 Wrap.label,颜色映射黑白图循环模式,Ramp Mask Texture Wrap,, +inspector.feature.颜色映射UV Wrap.label,颜色映射UV循环模式,Ramp UV Wrap,, +inspector.feature.颜色映射黑白图通道选择.label,颜色映射黑白图通道选择,Ramp Mask Channel,, +inspector.feature.颜色映射黑白图UV来源.label,颜色映射黑白图UV来源,Ramp Mask UV Source,, +inspector.feature.颜色映射贴图偏移速度.label,颜色映射贴图偏移速度,Ramp Texture Offset Speed,, +inspector.feature.颜色映射贴图旋转.label,颜色映射贴图旋转,Ramp Texture Rotation,, +inspector.feature.映射颜色.label,映射颜色,Ramp Colors,, +inspector.feature.Ramp颜色混合模式.label,Ramp颜色混合模式,Ramp Color Blend Mode,, +inspector.feature.颜色映射叠加颜色.label,颜色映射叠加颜色_hdr,Ramp Blend Color,, +inspector.feature.溶解.label,溶解,Dissolve,, +inspector.feature.溶解度黑白值测试.label,溶解度黑白值测试,Debug Dissolve Value,, +inspector.feature.溶解贴图.label,溶解贴图,Dissolve Texture,, +inspector.feature.溶解贴图 Wrap.label,溶解贴图循环模式,Dissolve Texture Wrap,, +inspector.feature.溶解贴图通道选择.label,溶解贴图通道选择,Dissolve Channel,, +inspector.feature.溶解贴图X轴偏移自定义曲线.label,溶解贴图X轴偏移自定义曲线,Dissolve Offset X Custom Data,, +inspector.feature.溶解贴图Y轴偏移自定义曲线.label,溶解贴图Y轴偏移自定义曲线,Dissolve Offset Y Custom Data,, +inspector.feature.溶解贴图UV来源.label,溶解贴图UV来源,Dissolve UV Source,, +inspector.feature.溶解贴图偏移速度.label,溶解贴图偏移速度,Dissolve Offset Speed,, +inspector.feature.溶解贴图旋转.label,溶解贴图旋转,Dissolve Texture Rotation,, +inspector.feature.溶解程序噪波混合.label,溶解程序噪波混合,Dissolve Program Noise Blend,, +inspector.feature.溶解值Pow.label,溶解值Pow,Dissolve Value Pow,, +inspector.feature.溶解强度.label,溶解强度,Dissolve Strength,, +inspector.feature.溶解强度自定义曲线.label,溶解强度自定义曲线,Dissolve Strength Custom Data,, +inspector.feature.溶解硬软度.label,溶解硬软度,Dissolve Softness,, +inspector.feature.溶解贴图扭曲强度.label,溶解贴图扭曲强度,Dissolve Texture Distortion Strength,, +inspector.feature.溶解描边.label,溶解描边,Dissolve Edge,, +inspector.feature.溶解描边颜色.label,溶解描边颜色,Dissolve Edge Color,, +inspector.feature.描边位置.label,描边位置,Edge Position,, +inspector.feature.描边软硬.label,描边软硬,Edge Softness,, +inspector.feature.溶解Ramp图功能.label,溶解Ramp图功能,Dissolve Ramp,, +inspector.feature.溶解Ramp模式.label,溶解Ramp模式,Dissolve Ramp Mode,, +inspector.feature.溶解Ramp图.label,溶解Ramp图,Dissolve Ramp Texture,, +inspector.feature.溶解Ramp图 Wrap.label,溶解Ramp图循环模式,Dissolve Ramp Texture Wrap,, +inspector.feature.Ramp颜色.label,Ramp颜色,Ramp Color,, +inspector.feature.Ramp颜色叠加.label,Ramp颜色叠加,Ramp Color Multiply,, +inspector.feature.溶解RampUV Wrap.label,溶解RampUV循环模式,Dissolve Ramp UV Wrap,, +inspector.feature.溶解Ramp混合模式.label,溶解Ramp混合模式,Dissolve Ramp Blend Mode,, +inspector.feature.溶解遮罩图(过程溶解).label,溶解遮罩图(过程溶解),Dissolve Mask (Process),, +inspector.feature.溶解遮罩模式.label,溶解遮罩模式,Dissolve Mask Mode,, +inspector.feature.溶解遮罩图.label,溶解遮罩图,Dissolve Mask Texture,, +inspector.feature.溶解遮罩图 Wrap.label,溶解遮罩图循环模式,Dissolve Mask Texture Wrap,, +inspector.feature.溶解遮罩图UV来源.label,溶解遮罩图UV来源,Dissolve Mask UV Source,, +inspector.feature.溶解遮罩图通道选择.label,溶解遮罩图通道选择,Dissolve Mask Channel,, +inspector.feature.溶解遮罩强度.label,溶解遮罩强度,Dissolve Mask Strength,, +inspector.feature.溶解遮罩图强度自定义曲线.label,溶解遮罩图强度自定义曲线,Dissolve Mask Strength Custom Data,, +inspector.feature.程序化噪波.label,程序化噪波,Program Noise,, +inspector.feature.程序化噪波测试颜色.label,程序化噪波测试颜色,Debug Program Noise,, +inspector.feature.程序噪波UV来源.label,程序噪波UV来源,Program Noise UV Source,, +inspector.feature.程序化噪波旋转.label,程序化噪波旋转,Program Noise Rotation,, +inspector.feature.Perlin噪波.label,Perlin噪波,Perlin Noise,, +inspector.feature.噪波1缩放.label,噪波1缩放,Noise 1 Scale,, +inspector.feature.噪波1速度.label,噪波1速度,Noise 1 Speed,, +inspector.feature.噪波1偏移.label,噪波1偏移,Noise 1 Offset,, +inspector.feature.噪波1偏移速度.label,噪波1偏移速度,Noise 1 Offset Speed,, +inspector.feature.噪波1偏移速度X自定义曲线.label,噪波1偏移速度X自定义曲线,Noise 1 Offset X Custom Data,, +inspector.feature.噪波1偏移速度Y自定义曲线.label,噪波1偏移速度Y自定义曲线,Noise 1 Offset Y Custom Data,, +inspector.feature.Voronoi噪波.label,Voronoi噪波,Voronoi Noise,, +inspector.feature.噪波2缩放.label,噪波2缩放,Noise 2 Scale,, +inspector.feature.噪波2速度.label,噪波2速度,Noise 2 Speed,, +inspector.feature.噪波2偏移.label,噪波2偏移,Noise 2 Offset,, +inspector.feature.噪波2偏移速度.label,噪波2偏移速度,Noise 2 Offset Speed,, +inspector.feature.噪波2偏移速度X自定义曲线.label,噪波2偏移速度X自定义曲线,Noise 2 Offset X Custom Data,, +inspector.feature.噪波2偏移速度Y自定义曲线.label,噪波2偏移速度Y自定义曲线,Noise 2 Offset Y Custom Data,, +inspector.feature.噪波1和噪波2混合系数.label,噪波1和噪波2混合系数,Noise 1/2 Blend,, +inspector.feature.两种程序噪波混合.label,两种程序噪波混合,Two Program Noise Blend,, +inspector.feature.公共UV.label,公共UV,Shared UV,, +inspector.feature.公共UV来源.label,公共UV来源,Shared UV Source,, +inspector.feature.公共UV Tiling.label,Tilling,Shared UV Tiling,, +inspector.feature.公共UV Offset.label,Offset,Shared UV Offset,, +inspector.feature.公共UV偏移速度.label,偏移速度,Shared UV Offset Speed,, +inspector.feature.旋转.label,旋转,Rotation,, +inspector.feature.公共UV X轴偏移自定义曲线.label,偏移X自定义曲线,Shared UV Offset X Custom Data,, +inspector.feature.公共UV Y轴偏移自定义曲线.label,偏移Y自定义曲线,Shared UV Offset Y Custom Data,, +inspector.feature.菲涅尔.label,菲涅尔,Fresnel,, +inspector.feature.菲涅尔测试颜色.label,菲涅尔值测试,Debug Fresnel,, +inspector.feature.菲涅尔模式.label,菲涅尔模式,Fresnel Mode,, +inspector.feature.菲涅尔颜色.label,菲涅尔颜色,Fresnel Color,, +inspector.feature.菲涅尔透明乘数.label,菲涅尔透明乘数,Fresnel Alpha Multiplier,, +inspector.feature.菲涅尔强度.label,菲涅尔强度,Fresnel Strength,, +inspector.feature.菲涅尔位置.label,菲涅尔位置,Fresnel Position,, +inspector.feature.菲涅尔位置自定义曲线.label,菲尼尔位置自定义曲线,Fresnel Position Custom Data,, +inspector.feature.菲涅尔范围Pow.label,菲涅尔范围Pow,Fresnel Range Pow,, +inspector.feature.菲涅尔硬度.label,菲涅尔硬度,Fresnel Hardness,, +inspector.feature.翻转菲涅尔.label,翻转菲涅尔,Invert Fresnel,, +inspector.feature.菲涅尔颜色受Alpha影响.label,菲涅尔颜色受Alpha影响,Fresnel Color Affected By Alpha,, +inspector.feature.菲涅尔方向偏移X.label,菲涅尔方向偏移X,Fresnel Direction Offset X,, +inspector.feature.菲涅尔方向偏移Y.label,菲涅尔方向偏移Y,Fresnel Direction Offset Y,, +inspector.feature.菲涅尔方向偏移Z.label,菲涅尔方向偏移Z,Fresnel Direction Offset Z,, +inspector.feature.顶点偏移.label,顶点偏移,Vertex Offset,, +inspector.feature.顶点偏移方向测试.label,顶点偏移方向测试,Debug Vertex Offset Direction,, +inspector.feature.顶点偏移贴图.label,顶点偏移贴图,Vertex Offset Texture,, +inspector.feature.顶点偏移贴图 Wrap.label,顶点偏移贴图循环模式,Vertex Offset Texture Wrap,, +inspector.feature.顶点偏移贴图UV来源.label,顶点偏移贴图UV来源,Vertex Offset UV Source,, +inspector.feature.顶点扰动X轴偏移自定义曲线.label,顶点扰动X轴偏移自定义曲线,Vertex Offset X Custom Data,, +inspector.feature.顶点扰动Y轴偏移自定义曲线.label,顶点扰动Y轴偏移自定义曲线,Vertex Offset Y Custom Data,, +inspector.feature.顶点偏移动画.label,顶点偏移动画,Vertex Offset Animation,, +inspector.feature.顶点偏移强度.label,顶点偏移强度,Vertex Offset Strength,, +inspector.feature.顶点扰动强度自定义曲线.label,顶点扰动强度自定义曲线,Vertex Offset Strength Custom Data,, +inspector.feature.顶点偏移从零开始.label,顶点偏移从零开始,Vertex Offset Starts From Zero,, +inspector.feature.顶点偏移使用法线方向.label,顶点偏移使用法线方向,Use Normal Direction,, +inspector.feature.顶点偏移本地方向X.label,顶点偏移本地方向X,Vertex Offset Local Direction X,, +inspector.feature.顶点偏移本地方向Y.label,顶点偏移本地方向Y,Vertex Offset Local Direction Y,, +inspector.feature.顶点偏移本地方向Z.label,顶点偏移本地方向Z,Vertex Offset Local Direction Z,, +inspector.feature.顶点偏移遮罩.label,顶点偏移遮罩,Vertex Offset Mask,, +inspector.feature.顶点偏移遮罩图.label,顶点偏移遮罩图,Vertex Offset Mask Texture,, +inspector.feature.顶点偏移遮罩图 Wrap.label,顶点偏移遮罩图循环模式,Vertex Offset Mask Texture Wrap,, +inspector.feature.顶点偏移遮罩图UV来源.label,顶点偏移遮罩图UV来源,Vertex Offset Mask UV Source,, +inspector.feature.顶点扰动遮罩X轴偏移自定义曲线.label,顶点扰动遮罩X轴偏移自定义曲线,Vertex Offset Mask X Custom Data,, +inspector.feature.顶点扰动遮罩Y轴偏移自定义曲线.label,顶点扰动遮罩Y轴偏移自定义曲线,Vertex Offset Mask Y Custom Data,, +inspector.feature.顶点偏移遮罩动画.label,顶点偏移遮罩动画,Vertex Offset Mask Animation,, +inspector.feature.顶点偏移遮罩强度.label,顶点偏移遮罩强度,Vertex Offset Mask Strength,, +inspector.feature.深度描边.label,深度描边,Depth Outline,, +inspector.feature.深度描边颜色.label,深度描边颜色,Depth Outline Color,, +inspector.feature.深度描边距离.label,深度描边距离,Depth Outline Distance,, +inspector.feature.深度贴花.label,深度贴花,Depth Decal,, +inspector.feature.遮蔽视差.label,遮蔽视差,Parallax,, +inspector.feature.视差贴图.label,视差贴图,Parallax Texture,, +inspector.feature.视差贴图 Wrap.label,视差贴图循环模式,Parallax Texture Wrap,, +inspector.feature.视差.label,视差,Parallax,, +inspector.feature.遮蔽视差最小层数.label,遮蔽视差最小层数,Parallax Min Layers,, +inspector.feature.遮蔽视差最大层数.label,遮蔽视差最大层数,Parallax Max Layers,, +inspector.feature.模板视差.label,模板视差,Portal,, +inspector.feature.模板视差蒙版.label,模板视差蒙版,Portal Mask,, +inspector.feature.序列帧融帧(丝滑).label,序列帧融帧(丝滑),Flipbook Blending,, +inspector.feature.VAT顶点动画图.label,VAT顶点动画图,VAT Vertex Animation Texture,, +inspector.feature.VAT模式.label,VAT模式,VAT Mode,, +inspector.feature.Houdini VAT Sub Mode.label,Houdini VAT Sub Mode,Houdini VAT Sub Mode,, +inspector.feature.VAT Frame CustomData.label,VAT Frame CustomData,VAT Frame CustomData,, +inspector.feature.Playback.label,Playback,Playback,, +inspector.feature.Auto Playback.label,Auto Playback,Auto Playback,, +inspector.feature.Display Frame.label,Display Frame,Display Frame,, +inspector.feature.Game Time at First Frame.label,Game Time at First Frame,Game Time at First Frame,, +inspector.feature.Playback Speed.label,Playback Speed,Playback Speed,, +inspector.feature.Houdini FPS.label,Houdini FPS,Houdini FPS,, +inspector.feature.Interframe Interpolation.label,Interframe Interpolation,Interframe Interpolation,, +inspector.feature.Animate First Frame.label,Animate First Frame,Animate First Frame,, +inspector.feature.Frame Count.label,Frame Count,Frame Count,, +inspector.feature.Bounds Metadata.label,Bounds Metadata,Bounds Metadata,, +inspector.feature.Bound Min X.label,Bound Min X,Bound Min X,, +inspector.feature.Bound Min Y.label,Bound Min Y,Bound Min Y,, +inspector.feature.Bound Min Z.label,Bound Min Z,Bound Min Z,, +inspector.feature.Bound Max X.label,Bound Max X,Bound Max X,, +inspector.feature.Bound Max Y.label,Bound Max Y,Bound Max Y,, +inspector.feature.Bound Max Z.label,Bound Max Z,Bound Max Z,, +inspector.feature.Textures.label,Textures,Textures,, +inspector.feature.Position Texture.label,Position Texture,Position Texture,, +inspector.feature.Position Texture 2.label,Position Texture 2,Position Texture 2,, +inspector.feature.Rotation Texture.label,Rotation Texture,Rotation Texture,, +inspector.feature.Color Texture.label,Color Texture,Color Texture,, +inspector.feature.Lookup Table.label,Lookup Table,Lookup Table,, +inspector.feature.Scale.label,Scale,Scale,, +inspector.feature.Global Piece Scale Multiplier.label,Global Piece Scale Multiplier,Global Piece Scale Multiplier,, +inspector.feature.Piece Scales in Position Alpha.label,Piece Scales in Position Alpha,Piece Scales in Position Alpha,, +inspector.feature.Particle Sprite.label,Particle Sprite,Particle Sprite,, +inspector.feature.Width Base Scale.label,Width Base Scale,Width Base Scale,, +inspector.feature.Height Base Scale.label,Height Base Scale,Height Base Scale,, +inspector.feature.Hide Overlapping Origin.label,Hide Overlapping Origin,Hide Overlapping Origin,, +inspector.feature.Origin Effective Radius.label,Origin Effective Radius,Origin Effective Radius,, +inspector.feature.Particles Can Spin.label,Particles Can Spin,Particles Can Spin,, +inspector.feature.Compute Spin from Heading.label,Compute Spin from Heading,Compute Spin from Heading,, +inspector.feature.Particle Spin Phase.label,Particle Spin Phase,Particle Spin Phase,, +inspector.feature.Scale by Velocity Amount.label,Scale by Velocity Amount,Scale by Velocity Amount,, +inspector.feature.Particle Texture U Scale.label,Particle Texture U Scale,Particle Texture U Scale,, +inspector.feature.Particle Texture V Scale.label,Particle Texture V Scale,Particle Texture V Scale,, +inspector.feature.Flags.label,Flags,Flags,, +inspector.feature.Positions Require Two Textures.label,Positions Require Two Textures,Positions Require Two Textures,, +inspector.feature.Use Compressed Normals (no rotTex).label,Use Compressed Normals (no rotTex),Use Compressed Normals (no rotTex),, +inspector.feature.Load Color Texture.label,Load Color Texture,Load Color Texture,, +inspector.feature.Load Lookup Table.label,Load Lookup Table,Load Lookup Table,, +inspector.feature.VAT texture.label,VAT texture,VAT Texture,, +inspector.feature.ImportScale.label,ImportScale,Import Scale,, +inspector.feature.TyFlow VAT Sub Mode.label,TyFlow VAT Sub Mode,TyFlow VAT Sub Mode,, +inspector.feature.Deforming skin.label,Deforming skin,Deforming Skin,, +inspector.feature.Skin bone count.label,Skin bone count,Skin Bone Count,, +inspector.feature.RGBA encoded.label,RGBA encoded,RGBA Encoded,, +inspector.feature.RGBA half.label,RGBA half,RGBA Half,, +inspector.feature.Gamma correction.label,Gamma correction,Gamma Correction,, +inspector.feature.VAT includes normals.label,VAT includes normals,VAT Includes Normals,, +inspector.feature.Affects shadows.label,Affects shadows,Affects Shadows,, +inspector.feature.Frame.label,Frame,Frame,, +inspector.feature.Frames.label,Frames,Frames,, +inspector.feature.Frame interpolation.label,Frame interpolation,Frame Interpolation,, +inspector.feature.Loop.label,Loop,Loop,, +inspector.feature.Interpolate loop.label,Interpolate loop,Interpolate Loop,, +inspector.feature.Autoplay.label,Autoplay,Autoplay,, +inspector.feature.AutoplaySpeed.label,AutoplaySpeed,Autoplay Speed,, +inspector.toolbar.ping.label,,,, +inspector.toolbar.ping.tip,跳到当前材质,Ping current material,, +inspector.toolbar.cleanUnusedTextures.label,,,, +inspector.toolbar.cleanUnusedTextures.tip,清除没有使用的贴图,Clean unused textures,, +inspector.toolbar.cleanUnusedTextures.undo,清除没有使用的贴图,Clean unused textures,, +inspector.toolbar.cleanUnusedTextures.log,清理 {0} 的无效贴图属性: {1},Cleaned unused texture property '{1}' on material '{0}',, +inspector.toolbar.copy.label,C,C,复制材质属性,Copy material properties +inspector.toolbar.paste.label,V,V,粘贴材质属性,Paste material properties +inspector.toolbar.paste.undo,粘贴材质属性,Paste material properties,, +inspector.toolbar.tierFormat.label,等级: {0},Tier: {0},, +inspector.toolbar.tierMixed.label,等级: Mixed,Tier: Mixed,, +inspector.toolbar.tierLow.label,低,Low,, +inspector.toolbar.tierMedium.label,中,Medium,, +inspector.toolbar.tierHigh.label,高,High,, +inspector.toolbar.tierUltra.label,顶配,Ultra,, +inspector.toolbar.tier.tip,NBShader分级,NBShader feature tier,, +inspector.toolbar.setTier.undo,设置 NBShader 分级,Set NBShader Feature Tier,, +inspector.toolbar.specialReset.label,R,R,特殊重置功能,Special reset tools +inspector.toolbar.resetAll.label,重置所有,Reset All,, +inspector.toolbar.resetAll.undo,重置所有特殊功能,Reset All Special Tools,, +inspector.toolbar.resetDisabledFeatureChildren.label,重置关闭功能子属性,Reset Disabled Feature Children,, +inspector.toolbar.resetDisabledFeatureChildren.undo,重置关闭功能子属性,Reset Disabled Feature Children,, +inspector.toolbar.resetSpecialUV.label,重置特殊UV通道,Reset Special UV Channel,, +inspector.toolbar.resetSpecialUV.undo,重置特殊UV通道,Reset Special UV Channel,, +inspector.toolbar.resetTwirl.label,重置旋转扭曲,Reset Twirl,, +inspector.toolbar.resetTwirl.undo,重置旋转扭曲,Reset Twirl,, +inspector.toolbar.resetPolar.label,重置极坐标,Reset Polar Coordinates,, +inspector.toolbar.resetPolar.undo,重置极坐标,Reset Polar Coordinates,, +inspector.toolbar.collapseAll.label,,,, +inspector.toolbar.collapseAll.tip,折叠所有控件,Collapse all controls,, +inspector.toolbar.collapseAll.undo,折叠所有控件,Collapse all controls,, +inspector.toolbar.help.label,,,, +inspector.toolbar.help.tip,说明文档,Documentation,, +inspector.toolbar.settings.tip,NBShader设置,NBShader settings,, +inspector.projectSettings.generalSection,基础设置,General Settings,, +inspector.projectSettings.defaultLanguage,默认语言,Default Language,, +inspector.projectSettings.languageMode.option.0,跟随编辑器,Follow Editor,, +inspector.projectSettings.languageMode.option.1,中文,Chinese,, +inspector.projectSettings.languageMode.option.2,英文,English,, +inspector.featureLevel.providerLabel,NBShader 分级,NBShader Feature Levels,, +inspector.featureLevel.help.message,配置 NBShader Catalog Keyword 和 Pass 的分级白名单、Unity Quality 绑定和运行时资源导出。构建脚本通过 NBShaderFeatureLevelEditorAPI.OverrideBuildStripExplicitTier 选择打包剔除等级。Catalog 外 Feature 会被忽略。,Configure NBShader managed Catalog keywords and shader passes per tier bind Unity Quality levels and export runtime settings. Build scripts select the build stripping tier through NBShaderFeatureLevelEditorAPI.OverrideBuildStripExplicitTier. Catalog-external features are ignored.,, +inspector.featureLevel.undo.changeKeyword,修改 NBShader Feature Keyword,Change NBShader Feature Keyword,, +inspector.featureLevel.undo.resetTierKeywords,重置 NBShader 等级 Keyword,Reset NBShader Tier Keywords,, +inspector.featureLevel.undo.resetQualityMapping,重置 NBShader Quality 映射,Reset NBShader Quality Mapping,, +inspector.featureLevel.undo.changeQualityBinding,修改 NBShader Quality 绑定,Change NBShader Quality Binding,, +inspector.featureLevel.table.title,分级功能表,Feature Level Matrix,, +inspector.featureLevel.column.feature.label,配置 / Feature,Config / Feature,等级设置和受管理的 Catalog Feature,Tier settings and managed Catalog features +inspector.featureLevel.column.description.label,Raw Keyword / 说明,Raw Keyword / Note,原始 Shader Keyword 或配置说明,Raw shader keyword or configuration note +inspector.featureLevel.row.quality.label,Quality 绑定,Quality Binding,每个 Unity Quality Level 只能属于一个 NBShader 等级,Each Unity Quality Level belongs to exactly one NBShader tier +inspector.featureLevel.desc.quality,Unity Quality Level,Unity Quality Level,, +inspector.featureLevel.quality.menuTip,点击可把 Unity Quality Level 移动到这个 NBShader 等级,Click to move Unity Quality levels to this NBShader tier,, +inspector.featureLevel.quality.noLevels,没有 Quality Level,No Quality Levels,, +inspector.featureLevel.quality.none,—,—,, +inspector.featureLevel.keyword.tooltip,Raw Keyword:{0}。该等级未勾选时会剔除使用此 Catalog Keyword 的 Variant。,Raw keyword: {0}. Unchecked in a tier strips variants using this Catalog keyword.,, +inspector.featureLevel.resetTierKeywords.button,重置等级 Keywords,Reset Tier Keywords,将 Feature 表格重置为内置默认值,Reset the keyword matrix to the built-in defaults +inspector.featureLevel.resetQualityMapping.button,重置 Quality 映射,Reset Quality Mapping,按默认 Quality 索引规则重置 Unity Quality 绑定,Reset Unity Quality bindings using the default quality-index rule +inspector.featureRuntimeSettings.updateFromProjectSettings.button,根据当前ProjectSetting更新配置,Update From Current Project Settings,将当前 Project Settings 数据写入这个 RuntimeSettings 配置资源,Write the current Project Settings data into this RuntimeSettings asset +inspector.featureRuntimeSettings.updateFromProjectSettings.successTitle,运行时配置已更新,Runtime Settings Updated,, +inspector.featureRuntimeSettings.updateFromProjectSettings.successMessage,当前 NBShader Project Settings 数据已写入这个 RuntimeSettings 配置资源,The current NBShader Project Settings data was written to this RuntimeSettings asset,, +inspector.featureLevel.openVariantCollectionBuilder.button,打开变体集合生成器,Open Variant Collection Builder,打开 NBShader 变体集合生成器,Open the NBShader variant collection builder +inspector.featureLevel.applyCurrentQualityTierToLoadedMaterials.button,应用当前 Quality 等级到已加载材质,Apply Current Quality Tier To Loaded Materials,将当前 Unity Quality 映射到的 NBShader 等级应用到所有已加载的 NBShader2 材质,Apply the tier bound to the current Unity Quality Level to all loaded NBShader2 materials +inspector.featureLevel.applyCurrentQualityTierToProjectMaterials.button,应用当前 Quality 等级到项目材质,Apply Current Quality Tier To Project Materials,扫描 Assets 并将当前 Unity Quality 映射到的 NBShader 等级应用到 NBShader2 材质资源,Scan Assets and apply the tier bound to the current Unity Quality Level to NBShader2 material assets +inspector.featureLevel.keyword.NB_DEBUG_DISSOLVE.label,调试溶解,Debug Dissolve,, +inspector.featureLevel.keyword.NB_DEBUG_DISTORT.label,调试扭曲,Debug Distort,, +inspector.featureLevel.keyword.NB_DEBUG_FRESNEL.label,调试菲涅尔,Debug Fresnel,, +inspector.featureLevel.keyword.NB_DEBUG_MASK.label,调试遮罩,Debug Mask,, +inspector.featureLevel.keyword.NB_DEBUG_PNOISE.label,调试程序噪声,Debug Program Noise,, +inspector.featureLevel.keyword.NB_DEBUG_VERTEX_OFFSET.label,调试顶点偏移,Debug Vertex Offset,, +inspector.featureLevel.keyword.VFX_SIX_WAY_ABSORPTION.label,六向光吸收,Six Way Absorption,, +inspector.featureLevel.keyword._ALPHAMODULATE_ON.label,Alpha 调制,Alpha Modulate,, +inspector.featureLevel.keyword._ALPHAPREMULTIPLY_ON.label,预乘 Alpha,Premultiply Alpha,, +inspector.featureLevel.keyword._ALPHATEST_ON.label,Alpha 裁剪,Alpha Test,, +inspector.featureLevel.keyword._COLORMAPBLEND.label,颜色图混合,Color Map Blend,, +inspector.featureLevel.keyword._COLOR_RAMP.label,颜色渐变,Color Ramp,, +inspector.featureLevel.keyword._DEPTH_DECAL.label,深度贴花,Depth Decal,, +inspector.featureLevel.keyword._DISSOLVE.label,溶解,Dissolve,, +inspector.featureLevel.keyword._DISTORT_REFRACTION.label,折射扭曲,Distort Refraction,, +inspector.featureLevel.keyword._EMISSION.label,自发光,Emission,, +inspector.featureLevel.keyword._FLIPBOOKBLENDING_ON.label,序列帧混合,Flipbook Blending,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_BLINN_PHONG.label,Blinn-Phong 光照,Blinn-Phong Lighting,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_HALF_LAMBERT.label,Half Lambert 光照,Half Lambert Lighting,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_PBR.label,PBR 光照,PBR Lighting,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_SIX_WAY.label,六向光照,Six Way Lighting,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_UNLIT.label,无光照,Unlit Lighting,, +inspector.featureLevel.keyword._HOUDINI_VAT_DYNAMIC_REMESH.label,Houdini VAT 动态重网格,Houdini VAT Dynamic Remesh,, +inspector.featureLevel.keyword._HOUDINI_VAT_PARTICLE_SPRITE.label,Houdini VAT 粒子精灵,Houdini VAT Particle Sprite,, +inspector.featureLevel.keyword._HOUDINI_VAT_RIGIDBODY.label,Houdini VAT 刚体,Houdini VAT Rigid Body,, +inspector.featureLevel.keyword._HOUDINI_VAT_SOFTBODY.label,Houdini VAT 软体,Houdini VAT Soft Body,, +inspector.featureLevel.keyword._MASKMAP_ON.label,遮罩贴图,Mask Map,, +inspector.featureLevel.keyword._MATCAP.label,MatCap,MatCap,, +inspector.featureLevel.keyword._NOISEMAP.label,噪声贴图,Noise Map,, +inspector.featureLevel.keyword._NOISEMAP_NORMALIZEED.label,噪声归一化,Noise Normalize,, +inspector.featureLevel.keyword._NORMALMAP.label,法线贴图,Normal Map,, +inspector.featureLevel.keyword._OVERRIDE_Z.label,Override Z,Override Z,, +inspector.featureLevel.keyword._PARALLAX_MAPPING.label,视差映射,Parallax Mapping,, +inspector.featureLevel.keyword._PARCUSTOMDATA_ON.label,粒子自定义数据,Particle Custom Data,, +inspector.featureLevel.keyword._PROGRAM_NOISE.label,程序噪声,Program Noise,, +inspector.featureLevel.keyword._SCREEN_DISTORT_MODE.label,屏幕扭曲,Screen Distort,, +inspector.featureLevel.keyword._SCRIPTABLETIME.label,可编程时间,Scriptable Time,, +inspector.featureLevel.keyword._SHARED_UV.label,共享 UV,Shared UV,, +inspector.featureLevel.keyword._SOFTPARTICLES_ON.label,软粒子,Soft Particles,, +inspector.featureLevel.keyword._SPECULAR_COLOR.label,高光颜色,Specular Color,, +inspector.featureLevel.keyword._STENCIL_WITHOUT_PLAYER.label,无 Player 模板,Stencil Without Player,, +inspector.featureLevel.keyword._TYFLOW_VAT_ABSOLUTE.label,TyFlow VAT 绝对模式,TyFlow VAT Absolute,, +inspector.featureLevel.keyword._TYFLOW_VAT_RELATIVE.label,TyFlow VAT 相对模式,TyFlow VAT Relative,, +inspector.featureLevel.keyword._TYFLOW_VAT_SKIN_PR.label,TyFlow VAT 皮肤 PR,TyFlow VAT Skin PR,, +inspector.featureLevel.keyword._TYFLOW_VAT_SKIN_PRSAVE.label,TyFlow VAT 皮肤 PR 保存,TyFlow VAT Skin PR Save,, +inspector.featureLevel.keyword._TYFLOW_VAT_SKIN_PRSXYZ.label,TyFlow VAT 皮肤 PRSXYZ,TyFlow VAT Skin PRSXYZ,, +inspector.featureLevel.keyword._TYFLOW_VAT_SKIN_R.label,TyFlow VAT 皮肤 R,TyFlow VAT Skin R,, +inspector.featureLevel.keyword._UNSCALETIME.label,非缩放时间,Unscaled Time,, +inspector.featureLevel.keyword._VAT.label,VAT,VAT,, +inspector.featureLevel.keyword._VAT_HOUDINI.label,Houdini VAT,Houdini VAT,, +inspector.featureLevel.keyword._VAT_TYFLOW.label,TyFlow VAT,TyFlow VAT,, +inspector.featureLevel.group.tooltip,点击折叠按钮显示或隐藏子级 Row,Click the foldout to show or hide child rows,, +inspector.featureLevel.desc.group,分组,Group,, +inspector.featureLevel.group.mode.label,模式设置,Mode,跟随材质面板的模式设置顺序,Matches the material inspector Mode order +inspector.featureLevel.group.transparent.label,透明模式,Transparent Mode,透明模式相关 Keyword,Transparent mode related keywords +inspector.featureLevel.group.time.label,时间模式,Time Mode,时间来源相关 Keyword,Time source related keywords +inspector.featureLevel.group.base.label,基本全局功能,Base,跟随材质面板的基本全局功能顺序,Matches the material inspector Base order +inspector.featureLevel.group.particle.label,粒子数据,Particle Data,粒子自定义数据相关 Keyword,Particle custom data related keywords +inspector.featureLevel.group.light.label,光照功能,Lighting,跟随材质面板的光照功能顺序,Matches the material inspector Lighting order +inspector.featureLevel.group.lightMode.label,光照模式,Light Mode,光照模式 Keyword,Light mode keywords +inspector.featureLevel.group.feature.label,特别功能,Feature,跟随材质面板的特别功能 Toggle 顺序,Matches the material inspector Feature toggle order +inspector.featureLevel.group.fresnel.label,菲涅尔,Fresnel,菲涅尔相关 Keyword,Fresnel related keywords +inspector.featureLevel.group.vertexOffset.label,顶点偏移,Vertex Offset,顶点偏移相关 Keyword,Vertex offset related keywords +inspector.featureLevel.group.depth.label,深度功能,Depth,深度相关 Keyword,Depth related keywords +inspector.featureLevel.group.vatMode.label,VAT 模式,VAT Mode,VAT 主模式 Keyword,VAT main mode keywords +inspector.featureLevel.group.houdiniVat.label,Houdini VAT,Houdini VAT,Houdini VAT 子模式 Keyword,Houdini VAT sub-mode keywords +inspector.featureLevel.group.tyflowVat.label,TyFlow VAT,TyFlow VAT,TyFlow VAT 子模式 Keyword,TyFlow VAT sub-mode keywords +inspector.featureLevel.column.cost.label,性能消耗,Performance Cost,估算启用该功能后的 Shader 性能消耗,Estimated shader cost when this feature is enabled +inspector.featureLevel.column.effect.label,功能说明,Feature Effect,简要说明该 Keyword 控制的功能,Short description of what this keyword enables +inspector.featureLevel.cost.low,低,Low,, +inspector.featureLevel.cost.medium,中,Medium,, +inspector.featureLevel.cost.high,高,High,, +inspector.featureLevel.cost.ultra,超高,Ultra,, +inspector.featureLevel.cost.tooltip,该 Keyword 估算的 Shader 性能消耗,Estimated shader performance cost for this keyword,, +inspector.featureLevel.desc.none,—,—,, +inspector.featureLevel.desc.config,配置,Config,, +inspector.featureLevel.effect.quality.label,绑定 Unity Quality 到 NBShader 等级,Bind Unity Quality Levels to NBShader tiers,每个 Unity Quality Level 只能属于一个 NBShader 等级,Each Unity Quality Level belongs to exactly one NBShader tier +inspector.featureLevel.keyword._CHROMATIC_ABERRATION.label,色散,Chromatic Aberration,, +inspector.featureLevel.keyword._COLOR_RAMP_MAP.label,颜色渐变贴图,Color Ramp Map,, +inspector.featureLevel.keyword._DEPTH_OUTLINE.label,深度描边,Depth Outline,, +inspector.featureLevel.keyword._DISSOLVE_MASK.label,溶解遮罩,Dissolve Mask,, +inspector.featureLevel.keyword._DISSOLVE_RAMP.label,溶解 Ramp,Dissolve Ramp,, +inspector.featureLevel.keyword._DISSOLVE_RAMP_MAP.label,溶解 Ramp 图,Dissolve Ramp Map,, +inspector.featureLevel.keyword._DISTANCE_FADE.label,距离淡化,Distance Fade,, +inspector.featureLevel.keyword._FRESNEL.label,菲涅尔,Fresnel,, +inspector.featureLevel.keyword._MASKMAP2_ON.label,遮罩贴图 2,Mask Map 2,, +inspector.featureLevel.keyword._MASKMAP3_ON.label,遮罩贴图 3,Mask Map 3,, +inspector.featureLevel.keyword._NOISE_MASKMAP.label,扭曲遮罩,Noise Mask Map,, +inspector.featureLevel.keyword._PROGRAM_NOISE_SIMPLE.label,程序噪声 Perlin,Program Noise Simple,, +inspector.featureLevel.keyword._PROGRAM_NOISE_VORONOI.label,程序噪声 Voronoi,Program Noise Voronoi,, +inspector.featureLevel.keyword._VERTEX_OFFSET.label,顶点偏移,Vertex Offset,, +inspector.featureLevel.keyword._VERTEX_OFFSET_MASKMAP.label,顶点偏移遮罩,Vertex Offset Mask Map,, +inspector.featureLevel.keyword.NB_DEBUG_DISSOLVE.effect,显示溶解数值方便调试,Shows dissolve values for debugging,, +inspector.featureLevel.keyword.NB_DEBUG_DISTORT.effect,显示扭曲强度方便调试,Shows distortion strength for debugging,, +inspector.featureLevel.keyword.NB_DEBUG_FRESNEL.effect,显示菲涅尔数值方便调试,Shows fresnel values for debugging,, +inspector.featureLevel.keyword.NB_DEBUG_MASK.effect,显示遮罩数值方便调试,Shows mask values for debugging,, +inspector.featureLevel.keyword.NB_DEBUG_PNOISE.effect,显示程序噪声数值方便调试,Shows procedural noise values for debugging,, +inspector.featureLevel.keyword.NB_DEBUG_VERTEX_OFFSET.effect,显示顶点偏移数值方便调试,Shows vertex offset values for debugging,, +inspector.featureLevel.keyword.VFX_SIX_WAY_ABSORPTION.effect,为六向光照增加吸收效果,Adds absorption response for six way lighting,, +inspector.featureLevel.keyword._ALPHAMODULATE_ON.effect,使用 Alpha 调制透明混合,Uses alpha modulation transparent blending,, +inspector.featureLevel.keyword._ALPHAPREMULTIPLY_ON.effect,使用预乘 Alpha 透明混合,Uses premultiplied alpha blending,, +inspector.featureLevel.keyword._ALPHATEST_ON.effect,按 Alpha 阈值裁剪像素,Cuts pixels by alpha threshold,, +inspector.featureLevel.keyword._CHROMATIC_ABERRATION.effect,分离颜色通道产生色散,Splits color channels for distortion fringe,, +inspector.featureLevel.keyword._COLORMAPBLEND.effect,混合额外的颜色渐变贴图,Blends an extra color gradient texture,, +inspector.featureLevel.keyword._COLOR_RAMP.effect,使用 Ramp 重新映射颜色,Remaps color through a ramp,, +inspector.featureLevel.keyword._COLOR_RAMP_MAP.effect,使用贴图作为颜色 Ramp 来源,Uses a texture as the color ramp source,, +inspector.featureLevel.keyword._DEPTH_DECAL.effect,使用场景深度投射贴花效果,Projects decal effect using scene depth,, +inspector.featureLevel.keyword._DEPTH_OUTLINE.effect,使用深度差生成描边效果,Creates outline effect using depth difference,, +inspector.featureLevel.keyword._OVERRIDE_Z.effect,写入固定相机眼深度到 SV_Depth,Writes a fixed camera eye depth through SV_Depth,, +inspector.featureLevel.keyword._DISSOLVE.effect,按噪声或贴图裁剪并混合溶解,Clips and blends pixels for dissolve,, +inspector.featureLevel.keyword._DISSOLVE_MASK.effect,使用遮罩控制过程溶解范围,Uses a process mask for dissolve,, +inspector.featureLevel.keyword._DISSOLVE_RAMP.effect,为溶解边缘增加 Ramp 着色,Adds ramp coloring to dissolve edges,, +inspector.featureLevel.keyword._DISSOLVE_RAMP_MAP.effect,使用贴图控制溶解 Ramp 颜色,Uses a texture for dissolve ramp color,, +inspector.featureLevel.keyword._DISTANCE_FADE.effect,根据相机距离淡化材质,Fades material by camera distance,, +inspector.featureLevel.keyword._DISTORT_REFRACTION.effect,使用折射方式计算扭曲,Uses refraction style distortion,, +inspector.featureLevel.keyword._EMISSION.effect,增加自发光颜色或贴图贡献,Adds emissive color or texture contribution,, +inspector.featureLevel.keyword._FLIPBOOKBLENDING_ON.effect,在序列帧之间进行平滑混合,Blends between flipbook frames,, +inspector.featureLevel.keyword._FRESNEL.effect,增加基于视角的边缘光,Adds view angle based rim lighting,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_BLINN_PHONG.effect,使用 Blinn Phong 光照模型,Uses Blinn Phong lighting,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_HALF_LAMBERT.effect,使用 Half Lambert 光照模型,Uses half Lambert lighting,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_PBR.effect,使用 PBR 光照计算,Uses PBR lighting calculations,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_SIX_WAY.effect,使用六向光照数据,Uses six way lighting data,, +inspector.featureLevel.keyword._FX_LIGHT_MODE_UNLIT.effect,使用无光照渲染,Uses unlit shading,, +inspector.featureLevel.keyword._HOUDINI_VAT_DYNAMIC_REMESH.effect,使用 Houdini 动态重网格 VAT 类型,Uses Houdini dynamic remesh VAT mode,, +inspector.featureLevel.keyword._HOUDINI_VAT_PARTICLE_SPRITE.effect,使用 Houdini 粒子精灵 VAT 类型,Uses Houdini particle sprite VAT mode,, +inspector.featureLevel.keyword._HOUDINI_VAT_RIGIDBODY.effect,使用 Houdini 刚体 VAT 类型,Uses Houdini rigid body VAT mode,, +inspector.featureLevel.keyword._HOUDINI_VAT_SOFTBODY.effect,使用 Houdini 软体 VAT 类型,Uses Houdini soft body VAT mode,, +inspector.featureLevel.keyword._MASKMAP_ON.effect,启用第一张遮罩贴图,Uses the first mask map,, +inspector.featureLevel.keyword._MASKMAP2_ON.effect,启用第二张遮罩贴图,Uses the second mask map,, +inspector.featureLevel.keyword._MASKMAP3_ON.effect,启用第三张遮罩贴图,Uses the third mask map,, +inspector.featureLevel.keyword._MATCAP.effect,增加 MatCap 贴图光照,Adds matcap lighting texture,, +inspector.featureLevel.keyword._NOISEMAP.effect,使用噪声贴图产生扭曲,Uses a noise map for distortion,, +inspector.featureLevel.keyword._NOISE_MASKMAP.effect,使用遮罩限制扭曲范围,Masks the distortion effect,, +inspector.featureLevel.keyword._NORMALMAP.effect,使用法线贴图增加光照细节,Uses normal map lighting detail,, +inspector.featureLevel.keyword._PARALLAX_MAPPING.effect,偏移 UV 模拟视差深度,Offsets UVs for parallax depth,, +inspector.featureLevel.keyword._PARCUSTOMDATA_ON.effect,读取粒子 Custom Data 通道,Reads particle custom data channels,, +inspector.featureLevel.keyword._PROGRAM_NOISE.effect,在 Shader 中生成程序噪声,Generates procedural noise in shader,, +inspector.featureLevel.keyword._PROGRAM_NOISE_SIMPLE.effect,启用简单程序噪声,Enables simple procedural noise,, +inspector.featureLevel.keyword._PROGRAM_NOISE_VORONOI.effect,启用 Voronoi 程序噪声,Enables Voronoi procedural noise,, +inspector.featureLevel.keyword._SCREEN_DISTORT_MODE.effect,采样屏幕纹理实现扭曲,Samples screen texture for distortion,, +inspector.featureLevel.keyword._SCRIPTABLETIME.effect,使用脚本传入的时间值,Uses script provided time value,, +inspector.featureLevel.keyword._SHARED_UV.effect,共享一组通用 UV 变换,Shares a common UV transform,, +inspector.featureLevel.keyword._SOFTPARTICLES_ON.effect,使用场景深度柔化粒子边缘,Softens particles using scene depth,, +inspector.featureLevel.keyword._SPECULAR_COLOR.effect,增加高光颜色控制,Adds specular color highlight,, +inspector.featureLevel.keyword._STENCIL_WITHOUT_PLAYER.effect,使用不含 Player 的模板遮罩,Uses stencil without player mask,, +inspector.featureLevel.keyword._TYFLOW_VAT_ABSOLUTE.effect,使用 TyFlow 绝对 VAT 模式,Uses TyFlow absolute VAT mode,, +inspector.featureLevel.keyword._TYFLOW_VAT_RELATIVE.effect,使用 TyFlow 相对 VAT 模式,Uses TyFlow relative VAT mode,, +inspector.featureLevel.keyword._TYFLOW_VAT_SKIN_PR.effect,使用 TyFlow Skin PR VAT 模式,Uses TyFlow skin PR VAT mode,, +inspector.featureLevel.keyword._TYFLOW_VAT_SKIN_PRSAVE.effect,使用 TyFlow Skin PR Save VAT 模式,Uses TyFlow skin PR save VAT mode,, +inspector.featureLevel.keyword._TYFLOW_VAT_SKIN_PRSXYZ.effect,使用 TyFlow Skin PRSXYZ VAT 模式,Uses TyFlow skin PRSXYZ VAT mode,, +inspector.featureLevel.keyword._TYFLOW_VAT_SKIN_R.effect,使用 TyFlow Skin R VAT 模式,Uses TyFlow skin R VAT mode,, +inspector.featureLevel.keyword._UNSCALETIME.effect,使用不受 TimeScale 影响的时间,Uses unscaled time,, +inspector.featureLevel.keyword._VAT.effect,启用顶点动画贴图播放,Enables vertex animation texture playback,, +inspector.featureLevel.keyword._VAT_HOUDINI.effect,使用 Houdini VAT 数据布局,Uses Houdini VAT data layout,, +inspector.featureLevel.keyword._VAT_TYFLOW.effect,使用 TyFlow VAT 数据布局,Uses TyFlow VAT data layout,, +inspector.featureLevel.keyword._VERTEX_OFFSET.effect,在 Shader 中偏移顶点,Offsets vertices in the shader,, +inspector.featureLevel.keyword._VERTEX_OFFSET_MASKMAP.effect,用贴图遮罩顶点偏移范围,Masks vertex offset by texture,, +inspector.featureLevel.saveCurrentAsDefault.button,保存当前配置为默认,Save Current Config as Default,将当前四个等级的 Keyword 配置写入 Package 默认 LevelAsset,Write the current tier keyword matrix into the package default LevelAsset +inspector.featureLevel.saveCurrentAsDefault.failedTitle,保存默认配置失败,Save Default Config Failed,, +inspector.featureLevel.saveCurrentAsDefault.failedMessage,无法写入 Package 默认 LevelAsset。请确认 Package 路径可写。,Could not write the package default LevelAsset. Please make sure the package path is writable.,, +inspector.featureLevel.dialog.ok,确定,OK,, +inspector.debugSymbols.providerLabel,NBShader2 调试符号,NBShader2 Debug Symbols,, +inspector.debugSymbols.help.message,通过改写 NBShader.shader 引用的包内 include 控制 NBShader2 编译调试符号。仅在外部工具调试 Shader 时开启。,Controls NBShader2 shader compiler debug symbols by rewriting the package include used by NBShader.shader. Enable only while debugging external shader tools.,, +inspector.debugSymbols.includeMismatch.message,ProjectSettings 值和包内 include 内容不一致。应用当前设置以重新同步 Shader 编译输入。,The ProjectSettings value and package include content do not match. Apply the current setting to resync the shader compiler input.,, +inspector.debugSymbols.enable.label,启用 NBShader2 调试符号,Enable NBShader2 Debug Symbols,将 #pragma enable_d3d11_debug_symbols 写入 NBShader2 调试 pragma include,Writes #pragma enable_d3d11_debug_symbols into the NBShader2 debug pragma include +inspector.debugSymbols.dirtyWarning.message,启用此选项会修改 NB_FX 包内的 NBShaderDebugPragmas.hlsl。除非明确需要 Shader 调试符号,否则不要提交开启状态的 include。,Enabling this option modifies NBShaderDebugPragmas.hlsl in the NB_FX package. Do not commit the enabled include unless shader debug symbols are deliberately required.,, +inspector.debugSymbols.cachingPreprocessor.label,Caching Shader Preprocessor,Caching Shader Preprocessor,#include_with_pragmas 需要启用 Caching Shader Preprocessor,#include_with_pragmas requires the Caching Shader Preprocessor +inspector.debugSymbols.cachingPreprocessorWarning.message,#include_with_pragmas 需要启用 Caching Shader Preprocessor。使用 NBShader2 调试符号前请先启用。,#include_with_pragmas requires the Caching Shader Preprocessor. Enable it before using NBShader2 debug symbols.,, +inspector.debugSymbols.settingsState.label,ProjectSettings 状态,ProjectSettings State,保存于 ProjectSettings/NBShaderFeatureLevels.asset 的状态,Saved state in ProjectSettings/NBShaderFeatureLevels.asset +inspector.debugSymbols.includeState.label,Include 文件状态,Include File State,NBShader.shader 实际使用的包内 include 内容,Actual package include content used by NBShader.shader +inspector.debugSymbols.status.enabled,已启用,Enabled,, +inspector.debugSymbols.status.disabled,已关闭,Disabled,, +inspector.debugSymbols.status.missing,缺失,Missing,, +inspector.debugSymbols.undo.changeSetting,修改 NBShader2 调试符号,Change NBShader2 Debug Symbols,, +inspector.debugSymbols.applyFailed.title,应用 NBShader2 调试符号失败,Apply NBShader2 Debug Symbols Failed,, +inspector.debugSymbols.applyFailed.message,无法写入 NBShaderDebugPragmas.hlsl:,Could not write NBShaderDebugPragmas.hlsl: ,, +inspector.debugSymbols.confirmEnable.title,启用 NBShader2 调试符号,Enable NBShader2 Debug Symbols,, +inspector.debugSymbols.confirmEnable.message,此操作会把 #pragma enable_d3d11_debug_symbols 写入 NB_FX 包内 include。开启期间 Shader 体积可能增加并关闭优化。,This writes #pragma enable_d3d11_debug_symbols into the NB_FX package include. Shader size can increase and optimizations are disabled while it is enabled.,, +inspector.debugSymbols.dialog.enable,启用,Enable,, +inspector.debugSymbols.dialog.cancel,取消,Cancel,, +inspector.debugSymbols.dialog.ok,确定,OK,, +inspector.debugSymbols.applySetting.button,应用当前设置到 Include,Apply Current Setting To Include,, +inspector.debugSymbols.pingInclude.button,选中调试开关include,Select Debug Toggle Include,, +inspector.debugSymbols.enableCachingPreprocessor.button,启用 Caching Shader Preprocessor,Enable Caching Shader Preprocessor,, +inspector.particleBaseMigration.providerLabel,ParticleBase 迁移,ParticleBase Migration,, +inspector.particleBaseMigration.settingsHelp,扫描引用旧版 ParticleBase Shader GUID 的材质资源,确认后迁移到 NBShader2。转换前请先做好资产备份或版本管理。,Scan material assets that reference the legacy ParticleBase shader GUID and migrate them to NBShader2 after confirmation. Back up assets or commit to version control before converting.,, +inspector.particleBaseMigration.openWindow.button,打开 ParticleBase 迁移窗口,Open ParticleBase Migration Window,, +inspector.particleBaseMigration.windowTitle,ParticleBase 迁移,ParticleBase Migration,, +inspector.particleBaseMigration.title,ParticleBase -> NBShader2,ParticleBase -> NBShader2,, +inspector.particleBaseMigration.windowWarning,此操作会修改材质 Shader 绑定并同步材质状态。转换前请先做好资产备份或版本管理。工具不会提供自动回退。,This operation changes material shader assignments and synchronized material state. Back up assets or commit to version control before converting. The tool does not provide an automatic rollback.,, +inspector.particleBaseMigration.scan.button,扫描 ParticleBase 材质,Scan ParticleBase Materials,, +inspector.particleBaseMigration.selectAll.button,全选,Select All,, +inspector.particleBaseMigration.selectNone.button,全不选,Select None,, +inspector.particleBaseMigration.scanPrompt,点击扫描查找引用 ParticleBase Shader 资源 GUID 的 .mat 资源。Shader 名称只作为回退匹配。,Click Scan to find .mat assets that reference the ParticleBase shader asset GUID. Shader name is only used as a fallback.,, +inspector.particleBaseMigration.noMaterials,没有找到 ParticleBase 材质资源。,No ParticleBase material assets were found.,, +inspector.particleBaseMigration.listSummary,找到 {0} 个材质资源。已选择:{1},Found {0} material asset(s). Selected: {1},, +inspector.particleBaseMigration.column.material,材质,Material,, +inspector.particleBaseMigration.column.match,匹配方式,Match,, +inspector.particleBaseMigration.column.path,路径,Path,, +inspector.particleBaseMigration.ping.button,定位,Ping,, +inspector.particleBaseMigration.convertSelected.button,转换选中的材质到 NBShader2,Convert Selected Materials To NBShader2,, +inspector.particleBaseMigration.progress.scanning,正在扫描材质 {0}/{1},Scanning materials {0}/{1},, +inspector.particleBaseMigration.scanCanceled,扫描已取消。取消前找到 {0} 个材质资源。,Scan canceled. Found {0} material asset(s) before canceling.,, +inspector.particleBaseMigration.scanComplete,扫描完成。找到 {0} 个 ParticleBase 材质资源。,Scan complete. Found {0} ParticleBase material asset(s).,, +inspector.particleBaseMigration.nbShader2Missing.title,缺少 NBShader2,NBShader2 Missing,, +inspector.particleBaseMigration.nbShader2Missing.message,无法加载 NBShader2 Shader 资源,迁移无法继续。,Could not load NBShader2 shader asset. Migration cannot continue.,, +inspector.particleBaseMigration.dialog.ok,确定,OK,, +inspector.particleBaseMigration.progress.converting,正在转换 {0}/{1}:{2},Converting {0}/{1}: {2},, +inspector.particleBaseMigration.failuresLogged,ParticleBase 迁移完成但存在失败项:,ParticleBase migration completed with failures:,, +inspector.particleBaseMigration.failure.loadMaterial,{0}:无法加载材质。,{0}: material could not be loaded.,, +inspector.particleBaseMigration.failure.noLongerParticleBase,{0}:已跳过,因为它不再引用 ParticleBase。,{0}: skipped because it no longer references ParticleBase.,, +inspector.particleBaseMigration.failure.exception,{0}:{1},{0}: {1},, +inspector.particleBaseMigration.match.converted,已转换,Converted,, +inspector.particleBaseMigration.confirm.title,确认 ParticleBase 迁移,Confirm ParticleBase Migration,, +inspector.particleBaseMigration.confirm.message,即将把 {0} 个材质资源从 ParticleBase 转换到 NBShader2。继续前请先做好资产备份或版本管理。工具不会提供自动回退。,You are about to convert {0} material asset(s) from ParticleBase to NBShader2. Back up assets or commit to version control before continuing. This tool does not provide an automatic rollback.,, +inspector.particleBaseMigration.dialog.convert,转换,Convert,, +inspector.particleBaseMigration.dialog.cancel,取消,Cancel,, +inspector.particleBaseMigration.conversionCanceled,转换已取消。已转换 {0}/{1} 个选中材质资源。,Conversion canceled. Converted {0}/{1} selected material asset(s).,, +inspector.particleBaseMigration.conversionComplete,转换完成。已转换 {0}/{1} 个选中材质资源。,Conversion complete. Converted {0}/{1} selected material asset(s).,, +inspector.particleBaseMigration.conversionFailures,{0} 个失败项已记录到 Console。,{0} failure(s) were logged to the Console.,, +inspector.particleBaseMigration.match.shaderGuid,Shader GUID,Shader GUID,, +inspector.particleBaseMigration.match.shaderObject,Shader 对象,Shader object,, +inspector.particleBaseMigration.match.shaderNameFallback,Shader 名称回退,Shader name fallback,, +inspector.particleBaseMigration.undo,迁移 ParticleBase 材质到 NBShader2,Migrate ParticleBase Materials To NBShader2,, diff --git a/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv.meta b/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv.meta new file mode 100644 index 00000000..3e204041 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4463b85718cfaeb4cb989148b4548e0a +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/NBShaderDebugSymbolsProjectSettings.cs b/Packages/NB_FX/NBShaders2/Editor/NBShaderDebugSymbolsProjectSettings.cs new file mode 100644 index 00000000..e48cbbe9 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/NBShaderDebugSymbolsProjectSettings.cs @@ -0,0 +1,339 @@ +using System; +using System.IO; +using System.Text; +using NBShaderEditor; +using NBShaders2.Editor.FeatureLevel; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor +{ + [InitializeOnLoad] + internal static class NBShaderDebugSymbolsSettingsProvider + { + internal const string DebugIncludeAssetPath = "Packages/com.xuanxuan.nb.fx/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl"; + private const string ShaderAssetPath = "Packages/com.xuanxuan.nb.fx/NBShaders2/Shader/NBShader.shader"; + private const string PackageJsonAssetPath = "Packages/com.xuanxuan.nb.fx/package.json"; + private const string PackageRootAssetPath = "Packages/com.xuanxuan.nb.fx/"; + + private static readonly Encoding Utf8NoBom = new UTF8Encoding(false); + + private const string DisabledIncludeContent = + "// NBShader2 shader compiler debug switches.\n" + + "// This file is intentionally included with #include_with_pragmas.\n" + + "\n" + + "#undef NB_SHADER_DEBUG_SYMBOLS\n" + + "#define NB_SHADER_DEBUG_SYMBOLS 0\n"; + + private const string EnabledIncludeContent = + "// NBShader2 shader compiler debug switches.\n" + + "// This file is intentionally included with #include_with_pragmas.\n" + + "\n" + + "#undef NB_SHADER_DEBUG_SYMBOLS\n" + + "#define NB_SHADER_DEBUG_SYMBOLS 1\n" + + "#pragma enable_d3d11_debug_symbols\n"; + + private enum IncludeDebugState + { + Missing, + Disabled, + Enabled + } + + static NBShaderDebugSymbolsSettingsProvider() + { + NBFXProjectSettings.RegisterSettingsSection( + "NBShaderDebugSymbols", + () => new GUIContent(Text("debugSymbols.providerLabel", "NBShader2 Debug Symbols")), + OnGUI, + new[] + { + "NBShader", + "Debug", + "Symbols", + "D3D11", + "enable_d3d11_debug_symbols" + }, + 90); + } + + private static void OnGUI(string searchContext) + { + var settings = NBShaderFeatureLevelProjectSettings.instance; + settings.EnsureInitialized(); + var includeState = GetIncludeDebugState(); + var includeEnabled = includeState == IncludeDebugState.Enabled; + + EditorGUILayout.HelpBox( + Text( + "debugSymbols.help.message", + "Controls NBShader2 shader compiler debug symbols by rewriting the package include used by NBShader.shader. Enable only while debugging external shader tools."), + MessageType.Info); + + DrawCachingShaderPreprocessorState(); + DrawStateRows(settings.enableDebugSymbols, includeState); + + if (settings.enableDebugSymbols != includeEnabled || includeState == IncludeDebugState.Missing) + { + EditorGUILayout.HelpBox( + Text( + "debugSymbols.includeMismatch.message", + "The ProjectSettings value and package include content do not match. Apply the current setting to resync the shader compiler input."), + MessageType.Warning); + + if (GUILayout.Button(ButtonContent("debugSymbols.applySetting", "Apply Current Setting To Include"))) + ApplySettingToInclude(settings, settings.enableDebugSymbols); + } + + var enabled = settings.enableDebugSymbols; + var toggleChanged = false; + using (new EditorGUILayout.HorizontalScope()) + { + EditorGUI.BeginChangeCheck(); + enabled = EditorGUILayout.Toggle( + Content( + "debugSymbols.enable", + "Enable NBShader2 Debug Symbols", + "Writes #pragma enable_d3d11_debug_symbols into the NBShader2 debug pragma include."), + settings.enableDebugSymbols); + toggleChanged = EditorGUI.EndChangeCheck(); + + if (GUILayout.Button(ButtonContent("debugSymbols.pingInclude", "Select Debug Toggle Include"), GUILayout.Width(180f))) + PingIncludeAsset(); + } + + if (toggleChanged) + { + if (!enabled || ConfirmEnableDebugSymbols()) + ApplySettingToInclude(settings, enabled); + } + + EditorGUILayout.HelpBox( + Text( + "debugSymbols.dirtyWarning.message", + "Enabling this option modifies NBShaderDebugPragmas.hlsl in the NB_FX package. Do not commit the enabled include unless shader debug symbols are deliberately required."), + MessageType.Warning); + + } + + internal static bool WriteDebugInclude(bool enabled, out string error) + { + error = null; + string physicalPath; + if (!TryGetPhysicalPath(DebugIncludeAssetPath, out physicalPath, out error)) + return false; + + var desiredContent = enabled ? EnabledIncludeContent : DisabledIncludeContent; + try + { + var folder = Path.GetDirectoryName(physicalPath); + if (!string.IsNullOrEmpty(folder) && !Directory.Exists(folder)) + Directory.CreateDirectory(folder); + + if (File.Exists(physicalPath) && string.Equals(File.ReadAllText(physicalPath), desiredContent, StringComparison.Ordinal)) + { + ReimportShaderAssets(); + return true; + } + + File.WriteAllText(physicalPath, desiredContent, Utf8NoBom); + ReimportShaderAssets(); + return true; + } + catch (Exception ex) + { + error = ex.Message; + return false; + } + } + + private static void DrawCachingShaderPreprocessorState() + { + var enabled = EditorSettings.cachingShaderPreprocessor; + EditorGUILayout.LabelField( + Content( + "debugSymbols.cachingPreprocessor", + "Caching Shader Preprocessor", + "#include_with_pragmas requires the Caching Shader Preprocessor."), + new GUIContent(enabled + ? Text("debugSymbols.status.enabled", "Enabled") + : Text("debugSymbols.status.disabled", "Disabled"))); + + if (enabled) + return; + + EditorGUILayout.HelpBox( + Text( + "debugSymbols.cachingPreprocessorWarning.message", + "#include_with_pragmas requires the Caching Shader Preprocessor. Enable it before using NBShader2 debug symbols."), + MessageType.Warning); + + if (GUILayout.Button(ButtonContent("debugSymbols.enableCachingPreprocessor", "Enable Caching Shader Preprocessor"))) + { + EditorSettings.cachingShaderPreprocessor = true; + ReimportShaderAssets(); + } + } + + private static void DrawStateRows(bool settingsEnabled, IncludeDebugState includeState) + { + EditorGUILayout.LabelField( + Content("debugSymbols.settingsState", "ProjectSettings State", "Saved state in ProjectSettings/NBShaderFeatureLevels.asset."), + new GUIContent(settingsEnabled + ? Text("debugSymbols.status.enabled", "Enabled") + : Text("debugSymbols.status.disabled", "Disabled"))); + + EditorGUILayout.LabelField( + Content("debugSymbols.includeState", "Include File State", "Actual package include content used by NBShader.shader."), + new GUIContent(GetIncludeStateText(includeState))); + } + + private static void ApplySettingToInclude(NBShaderFeatureLevelProjectSettings settings, bool enabled) + { + Undo.RecordObject(settings, Text("debugSymbols.undo.changeSetting", "Change NBShader2 Debug Symbols")); + + string error; + if (WriteDebugInclude(enabled, out error)) + { + if (settings.enableDebugSymbols != enabled) + { + settings.SetDebugSymbolsEnabled(enabled); + settings.SaveDebugSymbolsProjectSettings(); + } + + UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); + return; + } + + EditorUtility.DisplayDialog( + Text("debugSymbols.applyFailed.title", "Apply NBShader2 Debug Symbols Failed"), + Text("debugSymbols.applyFailed.message", "Could not write NBShaderDebugPragmas.hlsl: ") + error, + Text("debugSymbols.dialog.ok", "OK")); + } + + private static bool ConfirmEnableDebugSymbols() + { + return EditorUtility.DisplayDialog( + Text("debugSymbols.confirmEnable.title", "Enable NBShader2 Debug Symbols"), + Text( + "debugSymbols.confirmEnable.message", + "This writes #pragma enable_d3d11_debug_symbols into the NB_FX package include. Shader size can increase and optimizations are disabled while it is enabled."), + Text("debugSymbols.dialog.enable", "Enable"), + Text("debugSymbols.dialog.cancel", "Cancel")); + } + + private static IncludeDebugState GetIncludeDebugState() + { + string physicalPath; + string error; + if (!TryGetPhysicalPath(DebugIncludeAssetPath, out physicalPath, out error) || !File.Exists(physicalPath)) + return IncludeDebugState.Missing; + + try + { + return ContainsActiveDebugPragma(File.ReadAllText(physicalPath)) + ? IncludeDebugState.Enabled + : IncludeDebugState.Disabled; + } + catch + { + return IncludeDebugState.Missing; + } + } + + private static bool ContainsActiveDebugPragma(string content) + { + if (string.IsNullOrEmpty(content)) + return false; + + using (var reader = new StringReader(content)) + { + string line; + while ((line = reader.ReadLine()) != null) + { + var trimmed = line.TrimStart(); + if (trimmed.StartsWith("//", StringComparison.Ordinal)) + continue; + + if (trimmed.StartsWith("#pragma", StringComparison.Ordinal) && + trimmed.IndexOf("enable_d3d11_debug_symbols", StringComparison.Ordinal) >= 0) + { + return true; + } + } + } + + return false; + } + + private static bool TryGetPhysicalPath(string assetPath, out string physicalPath, out string error) + { + physicalPath = null; + error = null; + + var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(assetPath); + if (packageInfo == null) + packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(PackageJsonAssetPath); + + if (packageInfo == null || string.IsNullOrEmpty(packageInfo.resolvedPath)) + { + error = "Could not resolve package path for " + assetPath; + return false; + } + + if (!assetPath.StartsWith(PackageRootAssetPath, StringComparison.Ordinal)) + { + error = "Asset path is outside NB_FX package: " + assetPath; + return false; + } + + var relativePath = assetPath.Substring(PackageRootAssetPath.Length).Replace('/', Path.DirectorySeparatorChar); + physicalPath = Path.Combine(packageInfo.resolvedPath, relativePath); + return true; + } + + private static void ReimportShaderAssets() + { + AssetDatabase.ImportAsset(DebugIncludeAssetPath, ImportAssetOptions.ForceUpdate); + AssetDatabase.ImportAsset(ShaderAssetPath, ImportAssetOptions.ForceUpdate); + } + + private static void PingIncludeAsset() + { + var asset = AssetDatabase.LoadMainAssetAtPath(DebugIncludeAssetPath); + if (asset == null) + return; + + EditorGUIUtility.PingObject(asset); + Selection.activeObject = asset; + } + + private static string GetIncludeStateText(IncludeDebugState state) + { + switch (state) + { + case IncludeDebugState.Enabled: + return Text("debugSymbols.status.enabled", "Enabled"); + case IncludeDebugState.Disabled: + return Text("debugSymbols.status.disabled", "Disabled"); + default: + return Text("debugSymbols.status.missing", "Missing"); + } + } + + private static GUIContent Content(string key, string fallback, string tip) + { + return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip); + } + + private static GUIContent ButtonContent(string key, string fallback) + { + return NBShaderInspectorLocalization.MakeContent("inspector." + key + ".button", fallback); + } + + private static string Text(string key, string fallback) + { + return NBShaderInspectorLocalization.GetInspectorText(key, fallback); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/NBShaderDebugSymbolsProjectSettings.cs.meta b/Packages/NB_FX/NBShaders2/Editor/NBShaderDebugSymbolsProjectSettings.cs.meta new file mode 100644 index 00000000..6c023562 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/NBShaderDebugSymbolsProjectSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e55769c18e7943dc94e2223f195e0311 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI.cs b/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI.cs new file mode 100644 index 00000000..0f4f05df --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI.cs @@ -0,0 +1,138 @@ +using UnityEditor; +using UnityEngine; +using NBShader; + +namespace NBShaderEditor +{ + public class NBShaderGUI : ShaderGUI + { + private NBShaderRootItem _rootItem; + private string _currentLanguage; + + public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) + { + string currentLanguage = NBShaderInspectorLocalization.CurrentLanguage; + if (_rootItem == null || !string.Equals(_currentLanguage, currentLanguage, System.StringComparison.OrdinalIgnoreCase)) + { + _rootItem = new NBShaderRootItem(); + _currentLanguage = currentLanguage; + } + + _rootItem.OnGUI(materialEditor, properties); + } + } + + public class NBShaderRootItem : ShaderGUIRootItem + { + public NBShaderGUIContext Context { get; private set; } + public NBShaderSyncService SyncService { get; private set; } + + private ModeBigBlockItem _modeBlock; + private BaseOptionBigBlockItem _baseBlock; + private MainTexBigBlockItem _mainTexBlock; + private LightBigBlockItem _lightBlock; + private FeatureBigBlockItem _featureBlock; + private TABigBlockItem _taBlock; + private ParticleVertexStreamsItem _particleVertexStreamsItem; + private NBShaderGUIToolBar _toolBar; + + public override void InitFlags(System.Collections.Generic.List mats) + { + ShaderFlags = new System.Collections.Generic.List(); + foreach (Material mat in mats) + { + ShaderFlags.Add(new NBShaderFlags(mat)); + } + } + + public override void OnChildOnGUI() + { + if (Context == null) + { + Context = new NBShaderGUIContext(this); + SyncService = new NBShaderSyncService(this); + } + + Context.Refresh(); + + if (IsInit) + { + _toolBar = new NBShaderGUIToolBar(this); + _modeBlock = new ModeBigBlockItem(this, null); + _baseBlock = new BaseOptionBigBlockItem(this, null); + _mainTexBlock = new MainTexBigBlockItem(this, null); + _lightBlock = new LightBigBlockItem(this, null); + _featureBlock = new FeatureBigBlockItem(this, null); + _taBlock = new TABigBlockItem(this, null); + _particleVertexStreamsItem = new ParticleVertexStreamsItem(this, null); + } + + bool syncMaterialState = IsInit; + EditorGUI.BeginChangeCheck(); + + _toolBar ??= new NBShaderGUIToolBar(this); + _toolBar.DrawToolbar(); + + _modeBlock.OnGUI(); + _baseBlock.OnGUI(); + _mainTexBlock.OnGUI(); + if (Context.UIEffectEnabled == MixedBool.False) + { + _lightBlock.OnGUI(); + } + + _featureBlock.OnGUI(); + _taBlock.OnGUI(); + + if (EditorGUI.EndChangeCheck()) + { + syncMaterialState = true; + } + + if (syncMaterialState) + { + SyncService.SyncMaterialState(); + } + + _particleVertexStreamsItem.OnGUI(); + } + + public void ExecuteResetAllItems() + { + _modeBlock?.ExecuteReset(true); + _baseBlock?.ExecuteReset(true); + _mainTexBlock?.ExecuteReset(true); + _lightBlock?.ExecuteReset(true); + _featureBlock?.ExecuteReset(true); + _taBlock?.ExecuteReset(true); + } + + public System.Collections.Generic.IEnumerable GetToolbarResetRootItems() + { + if (_baseBlock != null) + { + yield return _baseBlock; + } + + if (_mainTexBlock != null) + { + yield return _mainTexBlock; + } + + if (_lightBlock != null) + { + yield return _lightBlock; + } + + if (_featureBlock != null) + { + yield return _featureBlock; + } + + if (_taBlock != null) + { + yield return _taBlock; + } + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI.cs.meta b/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI.cs.meta new file mode 100644 index 00000000..c8e7a2d5 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b18ce80080b45c7a5b2a0f8cc2492d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI_RULE.md b/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI_RULE.md new file mode 100644 index 00000000..6c81ad42 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI_RULE.md @@ -0,0 +1,335 @@ +# NBShaderGUI Rule + +## Purpose + +This rule defines the structure constraints for `NBShaders2/Editor/NBShaderGUI` and shared `ShaderGUIItems`. + +## Core Principles + +- Keep the GUI structure minimal and explicit. +- Do not add wrapper abstractions without a clear responsibility. +- `FoldOut` behavior and `parent-child composition` are two different concerns and must not be mixed. +- Common drawing items live in `XuanXuanRenderUtility/Editor/ShaderGUIItems`. +- Shared item names must not use the `NBShader` prefix. + +## Shared Item Rules + +All common material-property drawing items must live in `XuanXuanRenderUtility/Editor/ShaderGUIItems`, not in `NBShaders2/Editor/ShaderGUIItems`. + +Use shared items for common material property drawing: + +- `ToggleItem` +- `ColorItem` +- `TextureItem` +- `Vector2LineItem` +- `VectorComponentItem` +- `HelpBoxItem` + +Vector-related shared item classes should stay in one `VectorItem.cs` file. + +Do not create NBShader-prefixed wrappers for common drawing behavior. These names are not allowed for shared/general controls: + +- `NBShaderTogglePropertyItem` +- `NBShaderColorPropertyItem` +- `NBShaderTexturePropertyItem` +- `NBShaderVector2LinePropertyItem` +- `NBShaderVectorComponentPropertyItem` +- `NBShaderHelpBoxItem` + +Do not create wrappers that only set `PropertyName`, `GuiContent`, ranges, or visibility around an existing shared item. Prefer using the shared item directly, or create a concrete business item when there is real shader-specific behavior. + +Pure configuration items should be instantiated directly inside the owning block constructor. + +Use direct shared item construction for cases that only assign: + +- `PropertyName` +- `GuiContent` or `GUIContent` provider +- `RangePropertyName` +- `Min` / `Max` +- simple visibility predicates + +Example pattern: + +```csharp +_alphaAllItem = new ShaderGUISliderItem(rootItem, this) +{ + PropertyName = "_AlphaAll", + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("base.alphaAll", "Overall Alpha"), + RangePropertyName = "AlphaAllRangeVec" +}; +_alphaAllItem.InitTriggerByChild(); +``` + +Do not create a named class for this pattern, such as `AlphaAllItem`, unless it adds real behavior. + +A concrete item class is justified only when it owns shader-specific behavior, such as: + +- overriding `OnGUI`, `DrawBlock`, `OnEndChange`, `CheckIsPropertyModified`, or `ExecuteReset` +- synchronizing keywords, render queue, blend state, pass state, runtime flags, or context +- implementing a reusable layout/control behavior that belongs in shared `ShaderGUIItems` + +Current examples: + +- `ZTestItem` is allowed because it forces UIEffect depth behavior. +- `AddToPreMultiplySlider` is allowed because its reset default depends on `BlendMode`. +- Popup items are allowed when they update `Context`, keywords, render state, or child visibility. +- `BaseColorIntensityItem`, `AlphaAllItem`, and `CutOffSlider` are not allowed as named wrappers because they only configure shared float/slider items. + +Shared items must not reference: + +- `NBShaderRootItem` +- `NBShaderInspectorLocalization` +- NBShader-specific keyword, pass, or flag logic + +NBShader-specific labels should be passed into shared items through `GUIContent` providers from the call site. + +## Localization Rules + +NBShader Inspector user-facing text must go through `NBShaderInspectorLocalization`. + +- Use CSV keys in `NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv`. +- CSV format is `key,zh-CN,en-US,zh-CN-tip,en-US-tip`. +- Tooltip text belongs to the same row as its label key. If a row has no tooltip, leave the tip columns empty. +- Legacy `.tip` rows are only compatibility fallback for existing non-label message reads. New label tooltips must not create a separate `.tip` key. +- Language selection is project-wide and stored by `NBFXProjectSettings` in `ProjectSettings/NB_FXSettings.asset`. +- Language selection is edited through Project Settings > Project > NB_FX, not through Unity menu items. + +Fallback order: + +- current language +- `zh-CN` +- code fallback + +Key conventions: + +- normal labels use `inspector....label` +- label tooltips use the same key as the label and read the `-tip` column +- standalone tooltip/help text that is not attached to a `GUIContent` should use `.message` or another explicit text key +- pure messages use `inspector....message` +- buttons use `inspector....button` +- popup options use `inspector....option.` + +Code conventions: + +- Normal controls should call `NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip)` or pass a provider that calls it. The helper reads the label from `inspector..label` and the tooltip from the same CSV row first. +- HelpBox/message strings should call `NBShaderInspectorLocalization.GetInspectorText(key, fallback)`. +- Popup options should call `NBShaderInspectorLocalization.GetInspectorOptions(key, fallbackArray)` or update `PopUpNames` from an options provider. +- Shared `XuanXuanRenderUtility/Editor/ShaderGUIItems` must not reference `NBShaderInspectorLocalization`. +- Shared items that draw visible labels should expose `GUIContent` providers; NBShader call sites provide localized content. +- Technical identifiers stay untranslated unless they are deliberately shown as UI copy: shader property names, keyword names, pass names, enum protocol values, render queue numbers, and stencil config keys remain stable. + +## NBShaders2 Item Rules + +`NBShaders2/Editor/ShaderGUIItems` should only contain NBShader business structure: + +- top-level blocks +- secondary business blocks +- shader-specific popup items with side effects +- composite layout items such as the main texture layout +- feature-specific items that synchronize NBShader keywords, pass state, or runtime flags + +NBShader-specific item names are acceptable only when the item has NBShader business meaning. They must not be used for generic drawing controls. + +## Inheritance Rules + +### 1. `ShaderGUIItem` + +`ShaderGUIItem` is the base class for normal GUI items. + +Use it for: + +- leaf controls +- composite layout items +- parent-child grouping items without foldout +- texture layout parent items + +Important: + +- parent-child composition already belongs to `ShaderGUIItem` +- do not introduce extra “control base class” layers just to express parent-child grouping + +### 2. `BlockItem` + +`BlockItem` exists only to provide `FoldOut` behavior. + +Responsibilities: + +- owns `FoldOutPropertyName` +- owns foldout open/close lifecycle +- draws foldout title row +- draws children inside foldout content area + +It must not be used for: + +- non-foldout layout items +- generic feature/control wrappers + +### 3. `BigBlockItem` + +`BigBlockItem` inherits from `BlockItem`. + +Responsibilities: + +- defines the visual style of top-level blocks +- bold title +- spacing +- separator line + +`BigBlockItem` is a style specialization of `BlockItem`, not a different composition system. + +## Top-Level Block Rules + +These top-level sections should inherit `BigBlockItem`: + +- `ModeBigBlockItem` +- `BaseOptionBigBlockItem` +- `MainTexBigBlockItem` +- `LightBigBlockItem` +- `FeatureBigBlockItem` +- `TABigBlockItem` + +These are first-level inspector sections and should use persisted foldout state. + +## Secondary Block Rules + +Only use `BlockItem` for a secondary section when: + +- it has its own foldout state +- it is semantically a collapsible section +- it contains a group of child items + +If a section is only doing layout and grouping, it must stay on `ShaderGUIItem`. + +## Layout Rules + +All normal inspector row layout must be owned by `ShaderGUIItem`. + +Do not calculate label/control/reset positions independently in leaf items. Use the base rect pipeline: + +- `GetRect()` +- `ApplyGlobalRectCompensation()` +- `SplitLineRect()` +- `SplitControlAndResetRect()` + +Standard row responsibilities: + +- `BaseRect` is the compensated full row rect. +- `LabelRect` uses `GetLabelWidth(BaseRect)`. +- `GetLabelWidth()` has a fixed minimum (`MinLabelWidth`) and then grows by `LabelWidthRatio` once the inspector row is wide enough. +- Do not read or hardcode a fixed label width in business items. If a custom layout needs the normal label/control split, call `SplitLineRect()`. +- `ControlRect` starts after `LabelRect` and reserves reset space. +- `ResetRect` is fixed to the right side and uses `ResetButtonSize`. +- `ControlResetGap` is the only standard gap between control and reset. + +Do not add local magic numbers for reset width, reset gap, or standard control expansion in business items. If a layout constant is needed by more than one item, add it to `ShaderGUIItem`. + +Global row compensation: + +- `GlobalRectXOffset` shifts the whole row left/right. +- `GlobalRectWidthExpansion` expands the whole row width. +- These constants compensate meaningless inspector-side margin and must be applied at the rect entry point, before splitting label/control/reset. + +Any item that calls `EditorGUILayout.GetControlRect()` directly must immediately pass the result through `ApplyGlobalRectCompensation()`, unless there is a specific documented reason not to. + +Editor indent rules: + +- `EditorGUI.indentLevel` is only a hierarchy level counter. +- Do not introduce a separate per-block indent-count constant. +- Unity's internal per-level indent width is represented by `UnityEditorGUIIndentWidth`. +- The desired NBShader GUI visual indent width is represented by `EditorGUIIndentWidth`. +- `ApplyLabelIndentWidth()` converts Unity's built-in `EditorGUI.LabelField` indent width into the desired visual indent width for the NBShader GUI rect system. +- Direct `GUI.Label`, `GUI.Toggle`, texture preview rects, and other non-`EditorGUI.LabelField` labels do not get Unity's built-in label indent. Use `ApplyDirectLabelIndentWidth()` for their label start. +- Foldout arrows must be positioned from the final visual label text x, not from `BaseRect.x`. Use `ShaderGUIFoldOutHelper` / `GetEditorLabelTextX()` and do not call `EditorGUI.Foldout()` directly in business items. +- Do not hardcode a local texture or foldout indent width. Three-line texture groups must use `ApplyDirectLabelIndentWidth()` for the texture preview left edge and `SplitLineRect()` for Tilling/Offset control/reset positions. + +Control indent compensation: + +- `ControlIndentCompensation` is not the same thing as row indent. +- It only adjusts `ControlRect` by moving `x` left and increasing `width`. +- Use it only to compensate controls whose Unity internal drawing is shifted right inside the passed rect. +- Do not apply it to controls that draw exactly inside the passed rect, such as single-line `ColorField`; call `GetRect(false)` or `SplitLineRect(..., false)` for those rows. +- `EditorGUI.ColorField` draws the visible swatch through `EditorStyles.colorField.padding.Remove(position)`. Labeled color rows may compensate this padding inside `ColorItem`; no-label color rows keep their own local inset. Do not add Color-only constants to `ShaderGUIItem`. +- Keep `LabelRect` and `ResetRect` independent from this compensation. +- Composite layouts may disable it with `applyControlIndentCompensation: false` and then apply a local compensation only to the actual control rect when needed. + +Full-width or no-label rows: + +- Rows such as full-width color bars should not automatically use label/control semantics. +- If a row has no label, call `SplitControlAndResetRect()` directly and disable control compensation when the row must preserve its left edge. +- Reset alignment should still come from `SplitControlAndResetRect()`. + +Texture rows: + +- All texture object inputs should use the shared three-row texture layout (`TexturePropertyGroupItem` through `TextureItem`) instead of `MaterialEditor.TexturePropertySingleLine()`. +- Texture rows without editable Tilling/Offset should still reserve the three-row texture object area and leave the Tilling/Offset rows empty. +- Texture color rows remain separate no-label color rows after the three-row texture object group. + +## Animated Property Rules + +Animated property highlight must follow Unity's native material inspector behavior. + +Do not manually set animated controls to a fixed color such as `Color.red`. + +Use the shared `ShaderGUIItem` animated scope helpers: + +- `BeginAnimatedPropertyBackground(Rect totalPosition, MaterialProperty property)` +- `EndAnimatedPropertyBackground(bool scopeActive)` + +These helpers must use `MaterialEditor.BeginAnimatedCheck()` and `MaterialEditor.EndAnimatedCheck()`. They must not implement their own color decision with `AnimationMode.IsPropertyAnimated()`. + +Reason: + +- Unity's original `MaterialEditor.ShaderProperty()` wraps controls with `BeginAnimatedCheck()` / `EndAnimatedCheck()`. +- Unity chooses between animated, recorded, and candidate colors internally. +- Unity restores the previous `GUI.backgroundColor` through a stack, so nested drawing does not leak color state. + +Standard item rule: + +- Normal leaf items that use `ShaderGUIItem.OnGUI()` should rely on the base animated scope around `DrawController()`. + +Custom `OnGUI()` rule: + +- If an item overrides `OnGUI()` or draws multiple independent controls manually, it must explicitly wrap each actual editable control with the correct `MaterialProperty`. +- Do not wrap a composite row with one property if the row contains controls backed by different properties. +- Always call `EndAnimatedPropertyBackground()` in the same draw path after the control is drawn. + +Multi-property control rule: + +- `ShaderGUISliderItem` with `RangePropertyName` must wrap the min/max fields with the range vector property and the slider with the main float property. +- Texture scale/offset controls must wrap their `Vector2Field` controls with the texture property when editing `textureScaleAndOffset`, or with the vector property when editing a vector ST property. + +Animation refresh rule: + +- `ShaderGUIRootItem` must update incoming `MaterialProperty[]` into `PropertyInfoDic` every `OnGUI`. +- In animation mode, the material inspector should repaint so animated values and highlight state refresh while scrubbing or recording. +- Do not cache animated-state booleans. Caching property path strings is allowed for diagnostics or non-background queries. + +## Texture GUI Rules + +For texture-related GUI: + +- the texture layout parent item should inherit `ShaderGUIItem` +- it is a layout/composition item, not a `BlockItem` +- texture object field, texture color, and texture `Tilling/Offset` are separate GUI items +- the parent texture layout item is responsible only for arranging these child items +- texture layout must not move label text as a side effect of control compensation +- for `Tilling/Offset`, calculate label rects from the uncompensated vector rect first, then apply control compensation only to the `Vector2Field` rect if visual control alignment requires it +- texture, texture label, texture color, `Tilling/Offset`, and reset buttons must still use shared `ShaderGUIItem` layout constants where applicable +- texture ST animated highlight must use Unity's texture `MaterialProperty` animated check, not manual `_ST.x/y/z/w` color logic + +Required structure: + +- texture parent layout item + - texture object field item + - texture color item + - texture `Tilling/Offset` item + +## Anti-Rules + +Do not introduce these kinds of abstractions again unless there is a concrete need: + +- generic `ControlItem` base classes with no real behavior +- generic `FeatureItem` base classes with no real semantics +- wrapper layers that only rename existing base classes + +If an abstraction does not define a stable responsibility boundary, do not keep it. diff --git a/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI_RULE.md.meta b/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI_RULE.md.meta new file mode 100644 index 00000000..314ae42c --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/NBShaderGUI_RULE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0faa7bb86fa23764794c77e95761379e +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ParticleBaseMigrationWindow.cs b/Packages/NB_FX/NBShaders2/Editor/ParticleBaseMigrationWindow.cs new file mode 100644 index 00000000..42b6c7a3 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ParticleBaseMigrationWindow.cs @@ -0,0 +1,691 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using NBShaderEditor; +using UnityEditor; +using UnityEngine; + +namespace NBShaders2.Editor +{ + [InitializeOnLoad] + internal static class ParticleBaseMigrationSettingsProvider + { + static ParticleBaseMigrationSettingsProvider() + { + NBFXProjectSettings.RegisterSettingsSection( + "ParticleBaseMigration", + () => new GUIContent(Text("particleBaseMigration.providerLabel", "ParticleBase Migration")), + OnGUI, + new[] + { + "ParticleBase", + "NBShader2", + "Migration", + "Material", + "Shader GUID" + }, + 95); + } + + private static void OnGUI(string searchContext) + { + EditorGUILayout.HelpBox( + Text( + "particleBaseMigration.settingsHelp", + "Scan material assets that reference the legacy ParticleBase shader GUID and migrate them to NBShader2 after confirmation. Back up assets or commit to version control before converting."), + MessageType.Warning); + + if (GUILayout.Button(ButtonContent("particleBaseMigration.openWindow", "Open ParticleBase Migration Window"))) + { + ParticleBaseMigrationWindow.Open(); + } + } + + private static GUIContent ButtonContent(string key, string fallback) + { + return NBShaderInspectorLocalization.MakeContent("inspector." + key + ".button", fallback); + } + + private static string Text(string key, string fallback) + { + return NBShaderInspectorLocalization.GetInspectorText(key, fallback); + } + } + + internal sealed class ParticleBaseMigrationWindow : EditorWindow + { + private const string LegacyShaderGuidFallback = "7184a95c20fc1a441a8815af4c795ccd"; + private const string NBShader2Guid = "7787bfdacec31472ca6644d6e3616bd4"; + private const string LegacyShaderAssetPath = "Packages/com.xuanxuan.nb.fx/NBShaders/Shader/ParticleBase.shader"; + private const string NBShader2AssetPath = "Packages/com.xuanxuan.nb.fx/NBShaders2/Shader/NBShader.shader"; + private const string LegacyShaderName = "Effects/NBShader(Legacy)"; + private const string UndoNameFallback = "Migrate ParticleBase Materials To NBShader2"; + + private static readonly string[] LegacyFoldoutProperties = + { + "_W9ParticleShaderGUIFoldToggle", + "_W9ParticleShaderGUIFoldToggle1", + "_W9ParticleShaderGUIFoldToggle2" + }; + + private static readonly string[] NBShader2FoldoutProperties = + { + "_NBShaderGUIFoldToggle", + "_NBShaderGUIFoldToggle1", + "_NBShaderGUIFoldToggle2" + }; + + private readonly List _entries = new List(); + private Vector2 _scrollPosition; + private bool _scanned; + private string _statusMessage; + + public static void Open() + { + var window = GetWindow(Text("particleBaseMigration.windowTitle", "ParticleBase Migration")); + window.minSize = new Vector2(760f, 420f); + window.Show(); + } + + private void OnGUI() + { + titleContent = new GUIContent(Text("particleBaseMigration.windowTitle", "ParticleBase Migration")); + EditorGUILayout.LabelField(Text("particleBaseMigration.title", "ParticleBase -> NBShader2"), EditorStyles.boldLabel); + EditorGUILayout.HelpBox( + Text( + "particleBaseMigration.windowWarning", + "This operation changes material shader assignments and synchronized material state. Back up assets or commit to version control before converting. The tool does not provide an automatic rollback."), + MessageType.Warning); + + DrawToolbar(); + DrawStatus(); + DrawMaterialList(); + DrawConvertButton(); + } + + private void DrawToolbar() + { + using (new EditorGUILayout.HorizontalScope()) + { + if (GUILayout.Button(ButtonContent("particleBaseMigration.scan", "Scan ParticleBase Materials"), GUILayout.Height(24f))) + { + ScanMaterials(); + } + + EditorGUI.BeginDisabledGroup(_entries.Count == 0); + if (GUILayout.Button(ButtonContent("particleBaseMigration.selectAll", "Select All"), GUILayout.Width(96f), GUILayout.Height(24f))) + { + SetAllSelected(true); + } + + if (GUILayout.Button(ButtonContent("particleBaseMigration.selectNone", "Select None"), GUILayout.Width(96f), GUILayout.Height(24f))) + { + SetAllSelected(false); + } + + EditorGUI.EndDisabledGroup(); + } + } + + private void DrawStatus() + { + if (!string.IsNullOrEmpty(_statusMessage)) + { + EditorGUILayout.HelpBox(_statusMessage, MessageType.Info); + } + else if (!_scanned) + { + EditorGUILayout.HelpBox( + Text( + "particleBaseMigration.scanPrompt", + "Click Scan to find .mat assets that reference the ParticleBase shader asset GUID. Shader name is only used as a fallback."), + MessageType.Info); + } + else if (_entries.Count == 0) + { + EditorGUILayout.HelpBox( + Text("particleBaseMigration.noMaterials", "No ParticleBase material assets were found."), + MessageType.Info); + } + } + + private void DrawMaterialList() + { + if (_entries.Count == 0) + { + return; + } + + EditorGUILayout.Space(); + EditorGUILayout.LabelField( + FormatText("particleBaseMigration.listSummary", "Found {0} material asset(s). Selected: {1}", _entries.Count, CountSelected()), + EditorStyles.boldLabel); + + using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar)) + { + GUILayout.Label("", GUILayout.Width(24f)); + GUILayout.Label(Text("particleBaseMigration.column.material", "Material"), GUILayout.Width(240f)); + GUILayout.Label(Text("particleBaseMigration.column.match", "Match"), GUILayout.Width(160f)); + GUILayout.Label(Text("particleBaseMigration.column.path", "Path"), GUILayout.MinWidth(260f)); + } + + _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition); + for (int i = 0; i < _entries.Count; i++) + { + DrawMaterialRow(_entries[i]); + } + + EditorGUILayout.EndScrollView(); + } + + private static void DrawMaterialRow(MaterialMigrationEntry entry) + { + using (new EditorGUILayout.HorizontalScope()) + { + entry.selected = EditorGUILayout.Toggle(entry.selected, GUILayout.Width(24f)); + EditorGUILayout.ObjectField(entry.material, typeof(Material), false, GUILayout.Width(240f)); + GUILayout.Label(entry.matchSource, EditorStyles.miniLabel, GUILayout.Width(160f)); + + if (GUILayout.Button(ButtonContent("particleBaseMigration.ping", "Ping"), GUILayout.Width(48f))) + { + PingAsset(entry.assetPath); + } + + EditorGUILayout.SelectableLabel( + entry.assetPath, + EditorStyles.miniLabel, + GUILayout.Height(EditorGUIUtility.singleLineHeight), + GUILayout.MinWidth(220f)); + } + } + + private void DrawConvertButton() + { + EditorGUILayout.Space(); + EditorGUI.BeginDisabledGroup(CountSelected() == 0); + if (GUILayout.Button(ButtonContent("particleBaseMigration.convertSelected", "Convert Selected Materials To NBShader2"), GUILayout.Height(30f))) + { + ConvertSelectedMaterials(); + } + + EditorGUI.EndDisabledGroup(); + } + + private void ScanMaterials() + { + _entries.Clear(); + _scanned = true; + _statusMessage = null; + + string legacyShaderGuid = ResolveShaderGuid(LegacyShaderAssetPath, LegacyShaderGuidFallback); + Shader legacyShader = LoadShaderByGuidOrPath(legacyShaderGuid, LegacyShaderAssetPath); + string[] materialGuids = AssetDatabase.FindAssets("t:Material"); + var seenPaths = new HashSet(StringComparer.Ordinal); + bool canceled = false; + + try + { + for (int i = 0; i < materialGuids.Length; i++) + { + if (EditorUtility.DisplayCancelableProgressBar( + Text("particleBaseMigration.windowTitle", "ParticleBase Migration"), + FormatText("particleBaseMigration.progress.scanning", "Scanning materials {0}/{1}", i + 1, materialGuids.Length), + materialGuids.Length > 0 ? (float)i / materialGuids.Length : 1f)) + { + canceled = true; + break; + } + + string path = AssetDatabase.GUIDToAssetPath(materialGuids[i]); + if (string.IsNullOrEmpty(path) || + !path.EndsWith(".mat", StringComparison.OrdinalIgnoreCase) || + !seenPaths.Add(path)) + { + continue; + } + + Material material = AssetDatabase.LoadAssetAtPath(path); + string matchSource; + if (!IsLegacyParticleBaseMaterial(path, material, legacyShaderGuid, legacyShader, out matchSource)) + { + continue; + } + + _entries.Add(new MaterialMigrationEntry + { + assetPath = path, + material = material, + selected = true, + matchSource = matchSource + }); + } + } + finally + { + EditorUtility.ClearProgressBar(); + } + + _entries.Sort((a, b) => string.CompareOrdinal(a.assetPath, b.assetPath)); + _statusMessage = canceled + ? FormatText("particleBaseMigration.scanCanceled", "Scan canceled. Found {0} material asset(s) before canceling.", _entries.Count) + : FormatText("particleBaseMigration.scanComplete", "Scan complete. Found {0} ParticleBase material asset(s).", _entries.Count); + } + + private void ConvertSelectedMaterials() + { + List selectedEntries = GetSelectedEntries(); + if (selectedEntries.Count == 0) + { + return; + } + + Shader targetShader = LoadShaderByGuidOrPath(NBShader2Guid, NBShader2AssetPath); + if (targetShader == null) + { + EditorUtility.DisplayDialog( + Text("particleBaseMigration.nbShader2Missing.title", "NBShader2 Missing"), + Text("particleBaseMigration.nbShader2Missing.message", "Could not load NBShader2 shader asset. Migration cannot continue."), + Text("particleBaseMigration.dialog.ok", "OK")); + return; + } + + if (!ConfirmConversion(selectedEntries.Count)) + { + return; + } + + string legacyShaderGuid = ResolveShaderGuid(LegacyShaderAssetPath, LegacyShaderGuidFallback); + Shader legacyShader = LoadShaderByGuidOrPath(legacyShaderGuid, LegacyShaderAssetPath); + int convertedCount = 0; + bool canceled = false; + var failures = new List(); + int undoGroup = Undo.GetCurrentGroup(); + bool assetEditingStarted = false; + string undoName = Text("particleBaseMigration.undo", UndoNameFallback); + Undo.SetCurrentGroupName(undoName); + + try + { + AssetDatabase.StartAssetEditing(); + assetEditingStarted = true; + for (int i = 0; i < selectedEntries.Count; i++) + { + MaterialMigrationEntry entry = selectedEntries[i]; + if (EditorUtility.DisplayCancelableProgressBar( + Text("particleBaseMigration.windowTitle", "ParticleBase Migration"), + FormatText("particleBaseMigration.progress.converting", "Converting {0}/{1}: {2}", i + 1, selectedEntries.Count, entry.assetPath), + selectedEntries.Count > 0 ? (float)i / selectedEntries.Count : 1f)) + { + canceled = true; + break; + } + + if (ConvertMaterialEntry(entry, targetShader, legacyShaderGuid, legacyShader, undoName, failures)) + { + convertedCount++; + } + } + } + finally + { + if (assetEditingStarted) + { + AssetDatabase.StopAssetEditing(); + } + + EditorUtility.ClearProgressBar(); + Undo.CollapseUndoOperations(undoGroup); + } + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + if (failures.Count > 0) + { + Debug.LogWarning( + Text("particleBaseMigration.failuresLogged", "ParticleBase migration completed with failures:") + + "\n" + + string.Join("\n", failures.ToArray())); + } + + _statusMessage = BuildConversionStatus(convertedCount, selectedEntries.Count, canceled, failures.Count); + } + + private static bool ConvertMaterialEntry( + MaterialMigrationEntry entry, + Shader targetShader, + string legacyShaderGuid, + Shader legacyShader, + string undoName, + List failures) + { + try + { + Material material = AssetDatabase.LoadAssetAtPath(entry.assetPath); + if (material == null) + { + failures.Add(FormatText("particleBaseMigration.failure.loadMaterial", "{0}: material could not be loaded.", entry.assetPath)); + return false; + } + + string matchSource; + if (!IsLegacyParticleBaseMaterial(entry.assetPath, material, legacyShaderGuid, legacyShader, out matchSource)) + { + failures.Add(FormatText("particleBaseMigration.failure.noLongerParticleBase", "{0}: skipped because it no longer references ParticleBase.", entry.assetPath)); + return false; + } + + int[] legacyFoldoutValues = CaptureLegacyFoldoutValues(material, entry.assetPath); + Undo.RecordObject(material, undoName); + material.shader = targetShader; + ApplyNBShader2FoldoutValues(material, legacyFoldoutValues); + NBShaderSyncService.SyncMaterialState(material); + EditorUtility.SetDirty(material); + AssetDatabase.SaveAssetIfDirty(material); + + entry.material = material; + entry.matchSource = Text("particleBaseMigration.match.converted", "Converted"); + entry.selected = false; + return true; + } + catch (Exception ex) + { + failures.Add(FormatText("particleBaseMigration.failure.exception", "{0}: {1}", entry.assetPath, ex.Message)); + return false; + } + } + + private static bool ConfirmConversion(int count) + { + return EditorUtility.DisplayDialog( + Text("particleBaseMigration.confirm.title", "Confirm ParticleBase Migration"), + FormatText( + "particleBaseMigration.confirm.message", + "You are about to convert {0} material asset(s) from ParticleBase to NBShader2.\n\nBack up assets or commit to version control before continuing. This tool does not provide an automatic rollback.", + count), + Text("particleBaseMigration.dialog.convert", "Convert"), + Text("particleBaseMigration.dialog.cancel", "Cancel")); + } + + private static string BuildConversionStatus(int converted, int selected, bool canceled, int failureCount) + { + string status = canceled + ? FormatText("particleBaseMigration.conversionCanceled", "Conversion canceled. Converted {0}/{1} selected material asset(s).", converted, selected) + : FormatText("particleBaseMigration.conversionComplete", "Conversion complete. Converted {0}/{1} selected material asset(s).", converted, selected); + + if (failureCount > 0) + { + status += " " + FormatText("particleBaseMigration.conversionFailures", "{0} failure(s) were logged to the Console.", failureCount); + } + + return status; + } + + private static int[] CaptureLegacyFoldoutValues(Material material, string assetPath) + { + var values = new int[LegacyFoldoutProperties.Length]; + for (int i = 0; i < LegacyFoldoutProperties.Length; i++) + { + values[i] = int.MinValue; + if (material != null && material.HasProperty(LegacyFoldoutProperties[i])) + { + values[i] = material.GetInteger(LegacyFoldoutProperties[i]); + continue; + } + + int serializedValue; + if (TryReadSerializedIntegerProperty(assetPath, LegacyFoldoutProperties[i], out serializedValue)) + { + values[i] = serializedValue; + } + } + + return values; + } + + private static void ApplyNBShader2FoldoutValues(Material material, int[] legacyValues) + { + if (material == null || legacyValues == null) + { + return; + } + + int count = Math.Min(legacyValues.Length, NBShader2FoldoutProperties.Length); + for (int i = 0; i < count; i++) + { + if (legacyValues[i] == int.MinValue || !material.HasProperty(NBShader2FoldoutProperties[i])) + { + continue; + } + + material.SetInteger(NBShader2FoldoutProperties[i], legacyValues[i]); + } + } + + private static bool IsLegacyParticleBaseMaterial( + string assetPath, + Material material, + string legacyShaderGuid, + Shader legacyShader, + out string matchSource) + { + if (SerializedMaterialReferencesShaderGuid(assetPath, legacyShaderGuid)) + { + matchSource = Text("particleBaseMigration.match.shaderGuid", "Shader GUID"); + return true; + } + + if (material != null && material.shader != null) + { + if (legacyShader != null && material.shader == legacyShader) + { + matchSource = Text("particleBaseMigration.match.shaderObject", "Shader object"); + return true; + } + + if (string.Equals(material.shader.name, LegacyShaderName, StringComparison.Ordinal)) + { + matchSource = Text("particleBaseMigration.match.shaderNameFallback", "Shader name fallback"); + return true; + } + } + + matchSource = null; + return false; + } + + private static bool SerializedMaterialReferencesShaderGuid(string assetPath, string shaderGuid) + { + if (string.IsNullOrEmpty(assetPath) || string.IsNullOrEmpty(shaderGuid)) + { + return false; + } + + string physicalPath; + if (!TryGetPhysicalPath(assetPath, out physicalPath) || !File.Exists(physicalPath)) + { + return false; + } + + try + { + string content = File.ReadAllText(physicalPath); + return content.IndexOf("m_Shader:", StringComparison.Ordinal) >= 0 && + content.IndexOf("guid: " + shaderGuid, StringComparison.OrdinalIgnoreCase) >= 0; + } + catch + { + return false; + } + } + + private static bool TryReadSerializedIntegerProperty(string assetPath, string propertyName, out int value) + { + value = 0; + if (string.IsNullOrEmpty(assetPath) || string.IsNullOrEmpty(propertyName)) + { + return false; + } + + string physicalPath; + if (!TryGetPhysicalPath(assetPath, out physicalPath) || !File.Exists(physicalPath)) + { + return false; + } + + try + { + string prefix = "- " + propertyName + ":"; + using (var reader = new StringReader(File.ReadAllText(physicalPath))) + { + string line; + while ((line = reader.ReadLine()) != null) + { + string trimmed = line.Trim(); + if (!trimmed.StartsWith(prefix, StringComparison.Ordinal)) + { + continue; + } + + string rawValue = trimmed.Substring(prefix.Length).Trim(); + return int.TryParse(rawValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out value); + } + } + } + catch + { + return false; + } + + return false; + } + + private static bool TryGetPhysicalPath(string assetPath, out string physicalPath) + { + physicalPath = null; + if (string.IsNullOrEmpty(assetPath)) + { + return false; + } + + string normalizedPath = assetPath.Replace('\\', '/'); + if (normalizedPath.StartsWith("Assets/", StringComparison.Ordinal) || + string.Equals(normalizedPath, "Assets", StringComparison.Ordinal)) + { + string projectRoot = Path.GetFullPath(Path.Combine(Application.dataPath, "..")); + physicalPath = Path.Combine(projectRoot, normalizedPath.Replace('/', Path.DirectorySeparatorChar)); + return true; + } + + if (!normalizedPath.StartsWith("Packages/", StringComparison.Ordinal)) + { + return false; + } + + var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(normalizedPath); + if (packageInfo == null || string.IsNullOrEmpty(packageInfo.resolvedPath)) + { + return false; + } + + string packageRoot = "Packages/" + packageInfo.name + "/"; + if (!normalizedPath.StartsWith(packageRoot, StringComparison.Ordinal)) + { + return false; + } + + string relativePath = normalizedPath.Substring(packageRoot.Length).Replace('/', Path.DirectorySeparatorChar); + physicalPath = Path.Combine(packageInfo.resolvedPath, relativePath); + return true; + } + + private static string ResolveShaderGuid(string assetPath, string fallbackGuid) + { + string guid = AssetDatabase.AssetPathToGUID(assetPath); + return string.IsNullOrEmpty(guid) ? fallbackGuid : guid; + } + + private static Shader LoadShaderByGuidOrPath(string guid, string fallbackAssetPath) + { + string assetPath = string.IsNullOrEmpty(guid) ? null : AssetDatabase.GUIDToAssetPath(guid); + if (string.IsNullOrEmpty(assetPath)) + { + assetPath = fallbackAssetPath; + } + + return AssetDatabase.LoadAssetAtPath(assetPath); + } + + private void SetAllSelected(bool selected) + { + for (int i = 0; i < _entries.Count; i++) + { + _entries[i].selected = selected; + } + } + + private int CountSelected() + { + int count = 0; + for (int i = 0; i < _entries.Count; i++) + { + if (_entries[i].selected) + { + count++; + } + } + + return count; + } + + private List GetSelectedEntries() + { + var selectedEntries = new List(); + for (int i = 0; i < _entries.Count; i++) + { + if (_entries[i].selected) + { + selectedEntries.Add(_entries[i]); + } + } + + return selectedEntries; + } + + private static void PingAsset(string assetPath) + { + UnityEngine.Object asset = AssetDatabase.LoadMainAssetAtPath(assetPath); + if (asset == null) + { + return; + } + + Selection.activeObject = asset; + EditorGUIUtility.PingObject(asset); + } + + private static GUIContent ButtonContent(string key, string fallback) + { + return NBShaderInspectorLocalization.MakeContent("inspector." + key + ".button", fallback); + } + + private static string Text(string key, string fallback) + { + return NBShaderInspectorLocalization.GetInspectorText(key, fallback); + } + + private static string FormatText(string key, string fallback, params object[] args) + { + return string.Format(Text(key, fallback), args); + } + + private sealed class MaterialMigrationEntry + { + public string assetPath; + public Material material; + public string matchSource; + public bool selected; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ParticleBaseMigrationWindow.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ParticleBaseMigrationWindow.cs.meta new file mode 100644 index 00000000..bce8bbe4 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ParticleBaseMigrationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 748a4df299d449b49d8ee8055fe56dea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems.meta new file mode 100644 index 00000000..29a4901c --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 50e1a495cb24f82429902d4d23679f43 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/BaseOptionBigBlockItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/BaseOptionBigBlockItem.cs new file mode 100644 index 00000000..051bd166 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/BaseOptionBigBlockItem.cs @@ -0,0 +1,450 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; +using NBShader; + +namespace NBShaderEditor +{ + public enum RenderFace + { + Front = 2, + Back = 1, + Both = 0 + } + + public enum ForceZWriteMode + { + Default = 0, + ForceOn = 1, + ForceOff = 2 + } + + public class BaseOptionBigBlockItem : BigBlockItem + { + private readonly NBShaderRootItem _nbRootItem; + private readonly ShaderGUIFloatItem _baseColorIntensityItem; + private readonly ShaderGUISliderItem _alphaAllItem; + private readonly BlockItem _colorAdjustmentBlock; + private readonly ToggleItem _colorAdjustmentOnlyMainTexItem; + private readonly PropertyToggleBlockItem _hueShiftBlock; + private readonly ShaderGUISliderItem _hueShiftSlider; + private readonly CustomDataSelectItem _hueShiftCustomDataItem; + private readonly PropertyToggleBlockItem _saturabilityBlock; + private readonly ShaderGUISliderItem _saturabilitySlider; + private readonly CustomDataSelectItem _saturabilityCustomDataItem; + private readonly PropertyToggleBlockItem _contrastBlock; + private readonly ColorItem _contrastMidColorItem; + private readonly ShaderGUISliderItem _contrastSlider; + private readonly CustomDataSelectItem _contrastCustomDataItem; + private readonly PropertyToggleBlockItem _baseMapColorRefineBlock; + private readonly VectorComponentItem _baseMapColorRefineA; + private readonly VectorComponentItem _baseMapColorRefineBPower; + private readonly VectorComponentItem _baseMapColorRefineBMultiply; + private readonly VectorComponentItem _baseMapColorRefineLerp; + private readonly ToggleItem _colorMultiAlphaItem; + private readonly ZTestItem _zTestItem; + private readonly CullModeItem _cullItem; + private readonly ToggleItem _backFirstPassItem; + private readonly ForceZWriteItem _forceZWriteItem; + private readonly ToggleItem _affectsShadowsItem; + private readonly ToggleItem _transparentShadowDitherItem; + private readonly PropertyToggleBlockItem _baseBackColorBlock; + private readonly ColorItem _baseBackColorItem; + private readonly PropertyToggleBlockItem _distanceFadeBlock; + private readonly Vector2LineItem _fadeRangeItem; + private readonly PropertyToggleBlockItem _softParticlesBlock; + private readonly Vector2LineItem _softParticleFadeItem; + private readonly ToggleItem _stencilWithoutPlayerItem; + private readonly ToggleItem _ignoreVertexColorItem; + private readonly ShaderGUISliderItem _fogIntensityItem; + + public BaseOptionBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) : + base( + rootItem, + parentItem, + "_BaseOptionBigBlockItemFoldOut", + () => Content("block.base", "Base Options", "Global controls")) + { + _nbRootItem = rootItem; + + _baseColorIntensityItem = new ShaderGUIFloatItem(rootItem, this) + { + PropertyName = "_BaseColorIntensityForTimeline", + GuiContent = Content("base.colorIntensity", "Base Color Intensity") + }; + _baseColorIntensityItem.InitTriggerByChild(); + + _alphaAllItem = new ShaderGUISliderItem(rootItem, this) + { + PropertyName = "_AlphaAll", + GuiContent = Content("base.alphaAll", "Overall Alpha"), + RangePropertyName = "AlphaAllRangeVec" + }; + _alphaAllItem.InitTriggerByChild(); + + _colorAdjustmentBlock = new BlockItem( + rootItem, + this, + "_BaseColorAdjustmentFoldOut", + () => Content("base.colorAdjustment", "Color Adjustment")); + + _colorAdjustmentOnlyMainTexItem = new ToggleItem( + rootItem, + _colorAdjustmentBlock, + "_ColorAdjustmentOnlyAffectMainTex", + () => Content("base.colorAdjustment.onlyMainTex", "Only Affect Main Texture"), + enabled => rootItem.SyncService.ApplyToggleFlag( + NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX, + enabled)); + + _hueShiftBlock = new PropertyToggleBlockItem( + rootItem, + _colorAdjustmentBlock, + "_HueShiftFoldOut", + "_HueShift_Toggle", + () => Content("base.hueShift", "Hue Shift"), + NBShaderFlags.FLAG_BIT_HUESHIFT_ON); + _hueShiftSlider = new ShaderGUISliderItem(rootItem, _hueShiftBlock) + { + PropertyName = "_HueShift", + GuiContent = Content("base.hueShift.value", "Hue"), + Min = 0f, + Max = 1f + }; + _hueShiftSlider.InitTriggerByChild(); + _hueShiftCustomDataItem = new CustomDataSelectItem( + rootItem, + _hueShiftBlock, + NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT, + 0, + () => Content("base.hueShift.customData", "Hue Custom Data"), + IsParticleMode); + + _saturabilityBlock = new PropertyToggleBlockItem( + rootItem, + _colorAdjustmentBlock, + "_SaturabilityFoldOut", + "_ChangeSaturability_Toggle", + () => Content("base.saturability", "Saturation"), + NBShaderFlags.FLAG_BIT_SATURABILITY_ON); + _saturabilitySlider = new ShaderGUISliderItem(rootItem, _saturabilityBlock) + { + PropertyName = "_Saturability", + GuiContent = Content("base.saturability.value", "Saturation"), + RangePropertyName = "SaturabilityRangeVec" + }; + _saturabilitySlider.InitTriggerByChild(); + _saturabilityCustomDataItem = new CustomDataSelectItem( + rootItem, + _saturabilityBlock, + NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_SATURATE, + 1, + () => Content("base.saturability.customData", "Saturation Custom Data"), + IsParticleMode); + + _contrastBlock = new PropertyToggleBlockItem( + rootItem, + _colorAdjustmentBlock, + "_ContrastFoldOut", + "_Contrast_Toggle", + () => Content("base.contrast", "Contrast"), + NBShaderFlags.FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST, + 1); + _contrastMidColorItem = new ColorItem(rootItem, _contrastBlock, "_ContrastMidColor", () => Content("base.contrast.mid", "Contrast Mid Color")); + _contrastSlider = new ShaderGUISliderItem(rootItem, _contrastBlock) + { + PropertyName = "_Contrast", + GuiContent = Content("base.contrast.value", "Contrast"), + Min = 0f, + Max = 5f + }; + _contrastSlider.InitTriggerByChild(); + _contrastCustomDataItem = new CustomDataSelectItem( + rootItem, + _contrastBlock, + NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST, + 2, + () => Content("base.contrast.customData", "Contrast Custom Data"), + IsParticleMode); + + _baseMapColorRefineBlock = new PropertyToggleBlockItem( + rootItem, + _colorAdjustmentBlock, + "_BaseMapColorRefineFoldOut", + "_BaseMapColorRefine_Toggle", + () => Content("base.colorRefine", "Color Refine"), + NBShaderFlags.FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE, + 1); + _baseMapColorRefineA = new VectorComponentItem(rootItem, _baseMapColorRefineBlock, "_BaseMapColorRefine", 0, () => Content("base.colorRefine.a", "A Main Color Multiply"), false); + _baseMapColorRefineBPower = new VectorComponentItem(rootItem, _baseMapColorRefineBlock, "_BaseMapColorRefine", 1, () => Content("base.colorRefine.bPower", "B Main Color Power"), false); + _baseMapColorRefineBMultiply = new VectorComponentItem(rootItem, _baseMapColorRefineBlock, "_BaseMapColorRefine", 2, () => Content("base.colorRefine.bMultiply", "B After Power Multiply"), false); + _baseMapColorRefineLerp = new VectorComponentItem(rootItem, _baseMapColorRefineBlock, "_BaseMapColorRefine", 3, () => Content("base.colorRefine.lerp", "A/B Lerp"), true, 0f, 1f); + + _colorMultiAlphaItem = new ToggleItem( + rootItem, + _colorAdjustmentBlock, + "_ColorMultiAlpha", + () => Content("base.colorMultiAlpha", "Color Multiply Alpha"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA, enabled)); + + _zTestItem = new ZTestItem(rootItem, this); + _cullItem = new CullModeItem(rootItem, this); + + _backFirstPassItem = new ToggleItem( + rootItem, + this, + "_BackFirstPassToggle", + () => Content("base.backFirstPass", "Back First Pass"), + OnBackFirstPassChanged, + () => Is3DTransparent()); + + _forceZWriteItem = new ForceZWriteItem(rootItem, this); + _affectsShadowsItem = new ToggleItem( + rootItem, + this, + "_AffectsShadows", + () => Content("base.affectsShadows", "Affects Shadows"), + _ => rootItem.SyncService.SyncMaterialState(), + Is3DMode); + _transparentShadowDitherItem = new ToggleItem( + rootItem, + this, + "_TransparentShadowDitherToggle", + () => Content("base.transparentShadowDither", "Transparent Dither Shadows"), + _ => rootItem.SyncService.SyncMaterialState(), + ShouldDrawTransparentShadowDither); + + _baseBackColorBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_BaseBackColorFoldOut", + "_BaseBackColor_Toggle", + () => Content("base.backColor", "Back Color"), + NBShaderFlags.FLAG_BIT_PARTICLE_BACKCOLOR, + 0, + isVisible: Is3DMode); + _baseBackColorItem = new ColorItem(rootItem, _baseBackColorBlock, "_BaseBackColor", () => Content("base.backColor.color", "Back Color")); + + _distanceFadeBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_DistanceFadeFoldOut", + "_DistanceFade_Toggle", + () => Content("base.distanceFade", "Distance Fade"), + keyword: "_DISTANCE_FADE", + isVisible: Is3DMode); + _fadeRangeItem = new Vector2LineItem(rootItem, _distanceFadeBlock, "_Fade", true, () => Content("base.distanceFade.range", "Fade Range")); + + _softParticlesBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_SoftParticlesFoldOut", + "_SoftParticlesEnabled", + () => Content("base.softParticles", "Soft Particles"), + keyword: "_SOFTPARTICLES_ON", + isVisible: Is3DMode); + _softParticleFadeItem = new Vector2LineItem(rootItem, _softParticlesBlock, "_SoftParticleFadeParams", true, () => Content("base.softParticles.range", "Near/Far Fade")); + + _stencilWithoutPlayerItem = new NBShaderKeywordToggleItem( + rootItem, + this, + "_StencilWithoutPlayerToggle", + "_STENCIL_WITHOUT_PLAYER", + () => Content("base.stencilWithoutPlayer", "Stencil Without Player"), + OnStencilWithoutPlayerChanged, + Is3DMode); + + _ignoreVertexColorItem = new ToggleItem( + rootItem, + this, + "_IgnoreVetexColor_Toggle", + () => Content("base.ignoreVertexColor", "Ignore Vertex Color"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR, enabled, 1), + Is3DMode); + + _fogIntensityItem = new ShaderGUISliderItem(rootItem, this) + { + PropertyName = "_fogintensity", + GuiContent = Content("base.fogIntensity", "Fog Intensity"), + Min = 0f, + Max = 1f + }; + _fogIntensityItem.InitTriggerByChild(); + + InitTriggerByChild(); + } + + public override void DrawBlock() + { + _baseColorIntensityItem.OnGUI(); + _alphaAllItem.OnGUI(); + _colorAdjustmentBlock.OnGUI(); + _zTestItem.OnGUI(); + _cullItem.OnGUI(); + _backFirstPassItem.OnGUI(); + DrawBackFirstPassWarning(); + _forceZWriteItem.OnGUI(); + _affectsShadowsItem.OnGUI(); + _transparentShadowDitherItem.OnGUI(); + _baseBackColorBlock.OnGUI(); + _distanceFadeBlock.OnGUI(); + _softParticlesBlock.OnGUI(); + _stencilWithoutPlayerItem.OnGUI(); + _ignoreVertexColorItem.OnGUI(); + + if (Is3DMode()) + { + _fogIntensityItem.OnGUI(); + } + else if (_nbRootItem.PropertyInfoDic.ContainsKey("_fogintensity")) + { + _nbRootItem.PropertyInfoDic["_fogintensity"].Property.floatValue = 0f; + } + } + + private bool Is3DMode() + { + return _nbRootItem.Context.UIEffectEnabled == MixedBool.False; + } + + private bool Is3DTransparent() + { + return Is3DMode() && _nbRootItem.Context.TransparentMode == TransparentMode.Transparent; + } + + private bool IsParticleMode() + { + return _nbRootItem.Context.ParticleMode == MixedBool.True; + } + + private bool ShouldDrawTransparentShadowDither() + { + return Is3DTransparent() && + _nbRootItem.PropertyInfoDic.TryGetValue("_AffectsShadows", out ShaderPropertyInfo info) && + !info.Property.hasMixedValue && + info.Property.floatValue > 0.5f; + } + + private void DrawBackFirstPassWarning() + { + if (!Is3DTransparent() || + !_nbRootItem.PropertyInfoDic.ContainsKey("_BackFirstPassToggle") || + _nbRootItem.PropertyInfoDic["_BackFirstPassToggle"].Property.hasMixedValue || + _nbRootItem.PropertyInfoDic["_BackFirstPassToggle"].Property.floatValue <= 0.5f) + { + return; + } + + DrawLayoutHelpBox( + NBShaderInspectorLocalization.GetInspectorText( + "base.backFirstPass.warning", + "预渲染反面会导致打断动态合批,请谨慎使用。"), + MessageType.Warning); + } + + private void OnBackFirstPassChanged(bool enabled) + { + _nbRootItem.SyncService.ApplyShaderPass("SRPDefaultUnlit", enabled); + if (enabled && _nbRootItem.PropertyInfoDic.ContainsKey("_Cull")) + { + _nbRootItem.PropertyInfoDic["_Cull"].Property.floatValue = (float)RenderFace.Front; + } + } + + private void OnStencilWithoutPlayerChanged(bool enabled) + { + _nbRootItem.SyncService.ApplyStencilPreset(enabled ? "ParticleWithoutPlayer" : "ParticleBaseDefault"); + if (_nbRootItem.PropertyInfoDic.ContainsKey("_CustomStencilTest")) + { + _nbRootItem.PropertyInfoDic["_CustomStencilTest"].Property.floatValue = enabled ? 1f : 0f; + } + } + + private static GUIContent Content(string key, string fallback, string tip = "") + { + return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip); + } + } + + public class ZTestItem : ShaderGUIPopUpItem + { + private static readonly string[] Options = Enum.GetNames(typeof(CompareFunction)); + + public ZTestItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem: parentItem) + { + PropertyName = "_ZTest"; + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("base.ztest", "ZTest"); + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("base.ztest", Options); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (RootItem is NBShaderRootItem nbRootItem) + { + if (nbRootItem.Context.UIEffectEnabled == MixedBool.True) + { + if (!Mathf.Approximately(PropertyInfo.Property.floatValue, (float)CompareFunction.LessEqual)) + { + PropertyInfo.Property.floatValue = (float)CompareFunction.LessEqual; + } + + return; + } + + if (nbRootItem.Context.UIEffectEnabled == MixedBool.Mixed) + { + return; + } + } + + base.OnGUI(); + } + } + + public class CullModeItem : ShaderGUIPopUpItem + { + private static readonly string[] Options = { "Both", "Back", "Front" }; + + public CullModeItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem) + { + PropertyName = "_Cull"; + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("base.cull", "Cull"); + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("base.cull", Options); + InitTriggerByChild(); + } + + public override void OnGUI() + { + base.OnGUI(); + } + } + + public class ForceZWriteItem : ShaderGUIPopUpItem + { + private static readonly string[] Options = { "Default", "Force On", "Force Off" }; + + public ForceZWriteItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem) + { + PropertyName = "_ForceZWriteToggle"; + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("base.forceZWrite", "Force ZWrite"); + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("base.forceZWrite", Options); + InitTriggerByChild(); + } + + public override void OnGUI() + { + base.OnGUI(); + } + + public override void OnEndChange() + { + base.OnEndChange(); + if (RootItem is NBShaderRootItem nbRootItem) + { + nbRootItem.SyncService.SyncMaterialState(); + } + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/BaseOptionBigBlockItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/BaseOptionBigBlockItem.cs.meta new file mode 100644 index 00000000..c65f0a24 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/BaseOptionBigBlockItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 135aa1fd916c4155b15cada119fdf3fd +timeCreated: 1758549245 \ No newline at end of file diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/FeatureBigBlockItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/FeatureBigBlockItem.cs new file mode 100644 index 00000000..1932a282 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/FeatureBigBlockItem.cs @@ -0,0 +1,136 @@ +namespace NBShaderEditor +{ + public class FeatureBigBlockItem : BigBlockItem + { + public FeatureBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base( + rootItem, + parentItem, + "_FeatureBigBlockItemFoldOut", + () => NBShaderInspectorLocalization.MakeContent( + "inspector.block.feature.label", + "特效功能", + "inspector.block.feature.tip", + "遮罩、扭曲、溶解等特效功能")) + { + new MaskFeatureItem(rootItem, this); + new NoiseAndDistortFeatureItem(rootItem, this); + new ChromaticAberrationFeatureItem(rootItem, this); + new EmissionFeatureItem(rootItem, this); + new ColorBlendFeatureItem(rootItem, this); + new RampColorFeatureItem(rootItem, this); + new DissolveFeatureItem(rootItem, this); + new ProgramNoiseFeatureItem(rootItem, this); + new SharedUVFeatureItem(rootItem, this); + new FresnelFeatureItem(rootItem, this); + new VertexOffsetFeatureItem(rootItem, this); + new DepthFeatureItem(rootItem, this); + new ParallaxFeatureItem(rootItem, this); + new PortalFeatureItem(rootItem, this); + new FlipbookFeatureItem(rootItem, this); + new VatFeatureItem(rootItem, this); + + InitTriggerByChild(); + } + + public override void DrawBlock() + { + for (int i = 0; i < ChildrenItemList.Count; i++) + { + ShaderGUIItem child = ChildrenItemList[i]; + if (IsFeatureItemAllowed(child)) + { + child.OnGUI(); + } + } + } + + private bool IsFeatureItemAllowed(ShaderGUIItem item) + { + if (item is DepthFeatureItem) + { + var rootItem = (NBShaderRootItem)RootItem; + return rootItem.Context == null || + rootItem.Context.IsAnyKeywordAllowed("_DEPTH_DECAL", "_DEPTH_OUTLINE"); + } + + string keyword = GetFeatureKeyword(item); + return string.IsNullOrEmpty(keyword) || ((NBShaderRootItem)RootItem).Context.IsKeywordAllowed(keyword); + } + + private static string GetFeatureKeyword(ShaderGUIItem item) + { + if (item is MaskFeatureItem) + { + return "_MASKMAP_ON"; + } + + if (item is NoiseAndDistortFeatureItem) + { + return "_NOISEMAP"; + } + + if (item is ChromaticAberrationFeatureItem) + { + return "_CHROMATIC_ABERRATION"; + } + + if (item is EmissionFeatureItem) + { + return "_EMISSION"; + } + + if (item is ColorBlendFeatureItem) + { + return "_COLORMAPBLEND"; + } + + if (item is RampColorFeatureItem) + { + return "_COLOR_RAMP"; + } + + if (item is DissolveFeatureItem) + { + return "_DISSOLVE"; + } + + if (item is ProgramNoiseFeatureItem) + { + return "_PROGRAM_NOISE"; + } + + if (item is SharedUVFeatureItem) + { + return "_SHARED_UV"; + } + + if (item is FresnelFeatureItem) + { + return "_FRESNEL"; + } + + if (item is ParallaxFeatureItem) + { + return "_PARALLAX_MAPPING"; + } + + if (item is VatFeatureItem) + { + return "_VAT"; + } + + if (item is FlipbookFeatureItem) + { + return "_FLIPBOOKBLENDING_ON"; + } + + if (item is VertexOffsetFeatureItem) + { + return "_VERTEX_OFFSET"; + } + + return null; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/FeatureBigBlockItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/FeatureBigBlockItem.cs.meta new file mode 100644 index 00000000..188c7c48 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/FeatureBigBlockItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9bfc5d4ee5b1dc64caf81212c9880723 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features.meta new file mode 100644 index 00000000..785c3683 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f682036413e49019b4856f356996a4c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ChromaticAberrationFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ChromaticAberrationFeatureItem.cs new file mode 100644 index 00000000..31b43094 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ChromaticAberrationFeatureItem.cs @@ -0,0 +1,28 @@ +using NBShader; + +namespace NBShaderEditor +{ + internal sealed class ChromaticAberrationFeatureItem : FeatureToggleFoldOutItem + { + public ChromaticAberrationFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base( + rootItem, + parentItem, + "_ChromaticAberrationFoldOut", + "_Distortion_Choraticaberrat_Toggle", + "色散", + keyword: "_CHROMATIC_ABERRATION") + { + ShaderGUIItem chromaticNoiseAffect = new NoiseAffectItem(rootItem, this); + new ToggleItem( + rootItem, + chromaticNoiseAffect, + "_Distortion_Choraticaberrat_WithNoise_Toggle", + () => Content("色散强度受扭曲强度影响"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE, enabled)); + new VectorComponentItem(rootItem, this, "_DistortionDirection", 2, () => Content("色散强度"), false); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY, 0, () => Content("色散强度自定义曲线")); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ChromaticAberrationFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ChromaticAberrationFeatureItem.cs.meta new file mode 100644 index 00000000..8eff99ca --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ChromaticAberrationFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0e463cf92ee4725b57727544bc58488 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ColorBlendFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ColorBlendFeatureItem.cs new file mode 100644 index 00000000..d8deb0d1 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ColorBlendFeatureItem.cs @@ -0,0 +1,29 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class ColorBlendFeatureItem : FeatureToggleFoldOutItem + { + private static readonly string[] OnOffNames = { "关闭", "开启" }; + + public ColorBlendFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_ColorBlendBlockFoldOut", "_ColorBlendMap_Toggle", "渐变(颜色相乘)", keyword: "_COLORMAPBLEND") + { + AddTextureWithWrap(rootItem, this, "_ColorBlendMap", "颜色渐变贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_COLORBLENDMAP, "_ColorBlendColor"); + new UVModeSelectItem(rootItem, this, "_ColorBlendUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP, 0, () => Content("颜色渐变贴图UV来源"), "_ColorBlendMap"); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X, 3, () => Content("颜色渐变贴图X轴偏移自定义曲线")); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y, 3, () => Content("颜色渐变贴图Y轴偏移自定义曲线")); + new VectorComponentItem(rootItem, this, "_ColorBlendVec", 3, () => Content("颜色渐变贴图旋转"), true, 0f, 360f); + new Vector2LineItem(rootItem, this, "_ColorBlendMapOffset", true, () => Content("颜色渐变贴图偏移速度")); + ShaderGUIItem colorBlendNoiseAffect = new NoiseAffectItem(rootItem, this); + new VectorComponentItem(rootItem, colorBlendNoiseAffect, "_ColorBlendVec", 0, () => Content("颜色渐变扭曲强度"), true); + new FeaturePopupItem(rootItem, this, "_ColorBlendAlphaMultiplyMode", () => Content("颜色渐变图Alpha作用"), OnOffNames, + property => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE, property.floatValue > 0.5f)); + new VectorComponentItem(rootItem, this, "_ColorBlendVec", 2, () => Content("颜色渐变图Alpha强度"), true); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ColorBlendFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ColorBlendFeatureItem.cs.meta new file mode 100644 index 00000000..9ad5766e --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ColorBlendFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4e1e4d5240a4b748b50807573e22ab8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DepthFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DepthFeatureItem.cs new file mode 100644 index 00000000..3c3d66c0 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DepthFeatureItem.cs @@ -0,0 +1,64 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class DepthFeatureItem : ShaderGUIItem + { + public DepthFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem) + { + new DepthOutlineFeatureItem(rootItem, this); + new ToggleItem( + rootItem, + this, + "_DepthDecal_Toggle", + () => FeatureToggleFoldOutItem.Content("深度贴花"), + rootItem.SyncService.ApplyDepthDecalEnabled, + FeatureToggleFoldOutItem.TierVisible( + rootItem, + "_DEPTH_DECAL", + () => rootItem.Context.UIEffectEnabled != MixedBool.True)); + InitTriggerByChild(); + } + + public override void OnGUI() + { + for (int i = 0; i < ChildrenItemList.Count; i++) + { + ChildrenItemList[i].OnGUI(); + } + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + HasModified = false; + for (int i = 0; i < ChildrenItemList.Count; i++) + { + HasModified |= ChildrenItemList[i].HasModified; + } + + ParentItem?.CheckIsPropertyModified(true); + } + } + + internal sealed class DepthOutlineFeatureItem : FeatureToggleFoldOutItem + { + public DepthOutlineFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base( + rootItem, + parentItem, + "_DepthOutlineBlockFoldOut", + "_DepthOutline_Toggle", + "深度描边", + keyword: "_DEPTH_OUTLINE", + isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True) + { + new ColorItem(rootItem, this, "_DepthOutline_Color", () => Content("深度描边颜色")); + new Vector2LineItem(rootItem, this, "_DepthOutline_Vec", true, () => Content("深度描边距离")); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DepthFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DepthFeatureItem.cs.meta new file mode 100644 index 00000000..13ce9b1b --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DepthFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0482c5f68e7b4438bc494df4ebf47267 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DissolveFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DissolveFeatureItem.cs new file mode 100644 index 00000000..85d986ad --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DissolveFeatureItem.cs @@ -0,0 +1,83 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class DissolveFeatureItem : FeatureToggleFoldOutItem + { + private static readonly string[] RampSourceNames = { "渐变", "贴图" }; + private static readonly string[] BlendModeNames = { "叠加", "相乘" }; + private static readonly string[] DissolveMaskModeNames = { "Process Dissolve", "Dissolve Mask" }; + + public DissolveFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_DissolveBlockFoldOut", "_Dissolve_Toggle", "溶解", keyword: "_DISSOLVE") + { + new NBShaderKeywordToggleItem( + rootItem, + this, + "_NB_Debug_Dissolve", + "NB_DEBUG_DISSOLVE", + () => Content("溶解度黑白值测试"), + isVisible: null); + TextureRelatedFoldOutItem dissolveMapRelatedFoldOut = AddTextureWithRelatedFoldOut(rootItem, this, "_DissolveMap", "溶解贴图", "_DissolveMapFoldOut", NBShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_MAP); + new ColorChannelSelectItem(rootItem, dissolveMapRelatedFoldOut, NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP, 0, () => Content("溶解贴图通道选择")); + new CustomDataSelectItem(rootItem, dissolveMapRelatedFoldOut, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X, 1, () => Content("溶解贴图X轴偏移自定义曲线")); + new CustomDataSelectItem(rootItem, dissolveMapRelatedFoldOut, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y, 1, () => Content("溶解贴图Y轴偏移自定义曲线")); + new UVModeSelectItem(rootItem, dissolveMapRelatedFoldOut, "_DissolveUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP, 0, () => Content("溶解贴图UV来源"), "_DissolveMap"); + new Vector2LineItem(rootItem, dissolveMapRelatedFoldOut, "_DissolveOffsetRotateDistort", true, () => Content("溶解贴图偏移速度")); + new VectorComponentItem(rootItem, dissolveMapRelatedFoldOut, "_DissolveOffsetRotateDistort", 2, () => Content("溶解贴图旋转"), true, 0f, 360f); + new PNoiseBlendModeItem(rootItem, this, NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE, "_DissolvePNoiseBlendOpacity", () => Content("溶解程序噪波混合"), + () => rootItem.Context.ProgramNoiseEnabled == MixedBool.True); + new VectorComponentItem(rootItem, this, "_Dissolve", 1, () => Content("溶解值Pow"), true, 0.001f, 10f); + new VectorComponentRangeSliderItem(rootItem, this, "_Dissolve", 0, "DissolveXRangeVec", () => Content("溶解强度")); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY, 0, () => Content("溶解强度自定义曲线")); + new VectorComponentItem(rootItem, this, "_Dissolve", 3, () => Content("溶解硬软度"), true, 0.001f, 1f); + ShaderGUIItem dissolveNoiseAffect = new NoiseAffectItem(rootItem, this); + new VectorComponentItem(rootItem, dissolveNoiseAffect, "_DissolveOffsetRotateDistort", 3, () => Content("溶解贴图扭曲强度"), false); + + PropertyToggleBlockItem lineBlock = ToggleBlock(rootItem, "_DissolveLineFoldOut", "_DissolveLineMaskToggle", "溶解描边", + NBShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK, 1, parent: this); + new ColorItem(rootItem, lineBlock, "_DissolveLineColor", () => Content("溶解描边颜色")); + new VectorComponentRangeSliderItem(rootItem, lineBlock, "_Dissolve_Vec2", 0, "Dissolve2XRangeVec", () => Content("描边位置")); + new VectorComponentRangeSliderItem(rootItem, lineBlock, "_Dissolve_Vec2", 1, "Dissolve2YRangeVec", () => Content("描边软硬")); + + PropertyToggleBlockItem rampBlock = ToggleBlock(rootItem, "_DissolveRampFoldOut", "_Dissolve_useRampMap_Toggle", "溶解Ramp图功能", + parent: this, keyword: "_DISSOLVE_RAMP", + onValueChanged: _ => rootItem.SyncService.SyncMaterialState()); + Func isDissolveRampMapVisible = TierVisible(rootItem, "_DISSOLVE_RAMP_MAP", () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 1)); + new FeaturePopupItem(rootItem, rampBlock, "_DissolveRampSourceMode", () => Content("溶解Ramp模式"), RampSourceNames, + _ => rootItem.SyncService.SyncMaterialState(), + keyword: "_DISSOLVE_RAMP_MAP"); + AddTextureWithWrap(rootItem, rampBlock, "_DissolveRampMap", "溶解Ramp图", NBShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP, "_DissolveRampColor", + isDissolveRampMapVisible); + AddGradient(rootItem, rampBlock, "Ramp颜色", "_DissolveRampCount", "_DissolveRampColor", "_DissolveRampAlpha", hdr: true, + isVisible: () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 0)); + new TextureScaleOffsetItem(rootItem, rampBlock, "_DissolveRampMap", false, () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 0), TillingContent, OffsetContent); + new ColorItem(rootItem, rampBlock, "_DissolveRampColor", () => Content("Ramp颜色叠加"), () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 0)); + new WrapModeItem(rootItem, rampBlock, NBShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP, () => Content("溶解RampUV Wrap"), 2, + () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 0)); + new FeaturePopupItem(rootItem, rampBlock, "_DissolveRampColorBlendMode", () => Content("溶解Ramp混合模式"), BlendModeNames, + property => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY, property.floatValue > 0.5f, 1)); + + PropertyToggleBlockItem maskBlock = ToggleBlock(rootItem, "_DissolveMaskFoldOut", "_DissolveMask_Toggle", "溶解遮罩图(过程溶解)", + parent: this, keyword: "_DISSOLVE_MASK"); + new FeaturePopupItem(rootItem, maskBlock, "_DissolveMaskMode", () => Content("溶解遮罩模式"), DissolveMaskModeNames); + AddTextureWithWrap(rootItem, maskBlock, "_DissolveMaskMap", "溶解遮罩图", NBShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP); + new UVModeSelectItem(rootItem, maskBlock, "_DissolveMaskUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP, 0, () => Content("溶解遮罩图UV来源"), "_DissolveMaskMap"); + new ColorChannelSelectItem(rootItem, maskBlock, NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP, 0, () => Content("溶解遮罩图通道选择")); + new VectorComponentItem(rootItem, maskBlock, "_Dissolve", 2, () => Content("溶解遮罩强度"), false, isVisible: () => !IsDissolveMaskStrengthSlider(rootItem)); + new VectorComponentItem(rootItem, maskBlock, "_Dissolve", 2, () => Content("溶解遮罩强度"), true, 0f, 2f, () => IsDissolveMaskStrengthSlider(rootItem)); + new CustomDataSelectItem(rootItem, maskBlock, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY, 1, () => Content("溶解遮罩图强度自定义曲线")); + InitTriggerByChild(); + } + + private static bool IsDissolveMaskStrengthSlider(NBShaderRootItem rootItem) + { + return rootItem.PropertyInfoDic.TryGetValue("_DissolveMaskMode", out ShaderPropertyInfo info) && + !info.Property.hasMixedValue && + info.Property.floatValue > 0.5f; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DissolveFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DissolveFeatureItem.cs.meta new file mode 100644 index 00000000..962af85c --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/DissolveFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 64cae13520d842939c7d27d6ffadd01d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/EmissionFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/EmissionFeatureItem.cs new file mode 100644 index 00000000..5c32b72e --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/EmissionFeatureItem.cs @@ -0,0 +1,42 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class EmissionFeatureItem : FeatureToggleFoldOutItem + { + public EmissionFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_EmissionBlockFoldOut", "_EmissionEnabled", "流光(颜色相加)", keyword: "_EMISSION") + { + AddTextureWithWrap(rootItem, this, "_EmissionMap", "流光贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_EMISSIONMAP, "_EmissionMapColor"); + new UVModeSelectItem(rootItem, this, "_EmissionUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_EMISSION_MAP, 0, () => Content("流光贴图UV来源"), "_EmissionMap"); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X, 3, () => Content("流光贴图X轴偏移自定义曲线")); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y, 3, () => Content("流光贴图Y轴偏移自定义曲线")); + ShaderGUISliderItem emissionMapUVRotationItem = new ShaderGUISliderItem(rootItem, this) + { + PropertyName = "_EmissionMapUVRotation", + GuiContent = Content("流光贴图旋转"), + Min = 0f, + Max = 360f + }; + emissionMapUVRotationItem.InitTriggerByChild(); + new Vector2LineItem(rootItem, this, "_EmissionMapUVOffset", true, () => Content("流光贴图偏移速度")); + ShaderGUIItem emissionNoiseAffect = new NoiseAffectItem(rootItem, this); + ShaderGUIFloatItem emissionDistortionIntensityItem = new ShaderGUIFloatItem(rootItem, emissionNoiseAffect) + { + PropertyName = "_Emi_Distortion_intensity", + GuiContent = Content("流光贴图扭曲强度") + }; + emissionDistortionIntensityItem.InitTriggerByChild(); + ShaderGUIFloatItem emissionMapColorIntensityItem = new ShaderGUIFloatItem(rootItem, this) + { + PropertyName = "_EmissionMapColorIntensity", + GuiContent = Content("流光颜色强度") + }; + emissionMapColorIntensityItem.InitTriggerByChild(); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/EmissionFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/EmissionFeatureItem.cs.meta new file mode 100644 index 00000000..0a02ac1e --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/EmissionFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed7051253ed04c968aa25e96aa0e5d5d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureSupportItems.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureSupportItems.cs new file mode 100644 index 00000000..c852747e --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureSupportItems.cs @@ -0,0 +1,175 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class NoiseAffectItem : ShaderGUIItem + { + private readonly NBShaderRootItem _nbRootItem; + + public NoiseAffectItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem) + { + _nbRootItem = rootItem; + } + + public override void OnGUI() + { + bool previousMixedValue = EditorGUI.showMixedValue; + bool noiseEnabledHasMixedValue = _nbRootItem.Context.NoiseEnabled == MixedBool.Mixed; + using (new InheritedControlDisabledScope(_nbRootItem.Context.NoiseEnabled == MixedBool.False)) + { + for (int i = 0; i < ChildrenItemList.Count; i++) + { + EditorGUI.showMixedValue = noiseEnabledHasMixedValue; + ChildrenItemList[i].OnGUI(); + } + } + + EditorGUI.showMixedValue = previousMixedValue; + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + HasModified = false; + for (int i = 0; i < ChildrenItemList.Count; i++) + { + HasModified |= ChildrenItemList[i].HasModified; + } + + ParentItem?.CheckIsPropertyModified(true); + } + } + + internal sealed class FlipbookFeatureItem : ToggleItem + { + private readonly NBShaderRootItem _nbRootItem; + + public FlipbookFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base( + rootItem, + parentItem, + "_FlipbookBlending", + () => FeatureToggleFoldOutItem.Content("序列帧融帧(丝滑)"), + rootItem.SyncService.ApplyFlipbookEnabled) + { + _nbRootItem = rootItem; + } + + public override void DrawBlock() + { + if (PropertyInfo.Property.hasMixedValue || PropertyInfo.Property.floatValue <= 0.5f) + { + return; + } + + if (_nbRootItem.Context.MeshSourceMode == MeshSourceMode.Particle || + _nbRootItem.Context.MeshSourceMode == MeshSourceMode.UIParticle) + { + if (HasSpecialUVChannel()) + { + using (ParentControlDisabledScope()) + { + DrawLayoutHelpBox( + FeatureToggleFoldOutItem.Text( + "feature.flipbook.specialUvWarning.message", + "序列帧融帧和特殊UV通道同时开启,粒子序列帧应该影响UV0和UV1两个通道,特殊通道只能使用UV3(原始UV)"), + MessageType.Warning); + } + } + else + { + using (ParentControlDisabledScope()) + { + DrawLayoutHelpBox( + FeatureToggleFoldOutItem.Text( + "feature.flipbook.particleInfo.message", + "AnimationSheet的AffectUVChannel需要有UV0和UV1"), + MessageType.Info); + } + } + + return; + } + + if (_nbRootItem.Context.MeshSourceMode == MeshSourceMode.Mesh) + { + using (ParentControlDisabledScope()) + { + DrawLayoutHelpBox( + FeatureToggleFoldOutItem.Text( + "feature.flipbook.meshInfo.message", + "需要添加AnimationSheetHelper脚本"), + MessageType.Info); + } + } + } + + private bool HasSpecialUVChannel() + { + for (int i = 0; i < _nbRootItem.ShaderFlags.Count; i++) + { + if (_nbRootItem.ShaderFlags[i] is NBShaderFlags flags && + flags.CheckIsUVModeOn(NBShaderFlags.UVMode.SpecialUVChannel)) + { + return true; + } + } + + return false; + } + } + + internal sealed class VatFrameCustomDataItem : CustomDataSelectItem + { + private readonly Func _isVisible; + private readonly Func _anyVatFrameCustomDataVisible; + + public VatFrameCustomDataItem( + NBShaderRootItem rootItem, + ShaderGUIItem parentItem, + Func contentProvider, + Func isVisible, + Func anyVatFrameCustomDataVisible) + : base(rootItem, parentItem, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME, 2, contentProvider) + { + _isVisible = isVisible; + _anyVatFrameCustomDataVisible = anyVatFrameCustomDataVisible; + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + if (_anyVatFrameCustomDataVisible == null || !_anyVatFrameCustomDataVisible()) + { + ClearVatFrameCustomData(); + } + + return; + } + + base.OnGUI(); + } + + private void ClearVatFrameCustomData() + { + for (int i = 0; i < RootItem.ShaderFlags.Count; i++) + { + if (RootItem.ShaderFlags[i] is NBShaderFlags flags && flags.material != null) + { + if (flags.GetCustomDataFlag(NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME, 2) != + NBShaderFlags.CutomDataComponent.Off) + { + flags.SetCustomDataFlag( + NBShaderFlags.CutomDataComponent.Off, + NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME, + 2); + } + } + } + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureSupportItems.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureSupportItems.cs.meta new file mode 100644 index 00000000..4a2f2f27 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureSupportItems.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c8170a5849c4a5abf332cdf3832fa02 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureToggleFoldOutItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureToggleFoldOutItem.cs new file mode 100644 index 00000000..23a75958 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureToggleFoldOutItem.cs @@ -0,0 +1,276 @@ +using System; +using System.Collections.Generic; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal abstract class FeatureToggleFoldOutItem : PropertyToggleBlockItem + { + private const string LocalizationTableName = NBShaderInspectorLocalization.TableName; + private static readonly Dictionary ContentCache = + new Dictionary(StringComparer.Ordinal); + private static readonly Dictionary PopupOptionsCache = + new Dictionary(StringComparer.Ordinal); + private static string s_CacheLanguage; + + protected FeatureToggleFoldOutItem( + NBShaderRootItem rootItem, + ShaderGUIItem parentItem, + string foldOutPropertyName, + string togglePropertyName, + string label, + int flagBits = 0, + int flagIndex = 0, + string keyword = null, + Action onValueChanged = null, + Func isVisible = null, + bool bold = true) + : base( + rootItem, + parentItem, + foldOutPropertyName, + togglePropertyName, + () => Content(label), + flagBits, + flagIndex, + keyword, + onValueChanged: onValueChanged, + isVisible: isVisible, + bold: bold) + { + } + + protected TextureRelatedFoldOutItem AddTextureWithRelatedFoldOut( + NBShaderRootItem rootItem, + ShaderGUIItem parent, + string texturePropertyName, + string label, + string foldOutPropertyName, + int wrapFlag, + string colorPropertyName = null, + Func isVisible = null) + { + new TextureItem( + rootItem, + parent, + texturePropertyName, + () => Content(label), + colorPropertyName, + isVisible: isVisible, + tillingContentProvider: TillingContent, + offsetContentProvider: OffsetContent); + TextureRelatedFoldOutItem relatedFoldOut = new TextureRelatedFoldOutItem( + rootItem, + parent, + foldOutPropertyName, + texturePropertyName, + () => Content(label + "相关功能"), + isVisible); + new WrapModeItem(rootItem, relatedFoldOut, wrapFlag, () => Content(label + " Wrap"), 2); + return relatedFoldOut; + } + + protected void AddTextureWithWrap( + NBShaderRootItem rootItem, + ShaderGUIItem parent, + string texturePropertyName, + string label, + int wrapFlag, + string colorPropertyName = null, + Func isVisible = null) + { + new TextureItem( + rootItem, + parent, + texturePropertyName, + () => Content(label), + colorPropertyName, + isVisible: isVisible, + tillingContentProvider: TillingContent, + offsetContentProvider: OffsetContent); + new WrapModeItem(rootItem, parent, wrapFlag, () => Content(label + " Wrap"), 2, isVisible); + } + + protected PropertyToggleBlockItem ToggleBlock( + NBShaderRootItem rootItem, + string foldOutPropertyName, + string togglePropertyName, + string label, + int flagBits = 0, + int flagIndex = 0, + ShaderGUIItem parent = null, + string keyword = null, + Action onValueChanged = null, + Func isVisible = null, + bool bold = false) + { + return new PropertyToggleBlockItem( + rootItem, + parent ?? this, + foldOutPropertyName, + togglePropertyName, + () => Content(label), + flagBits, + flagIndex, + keyword, + onValueChanged: onValueChanged, + isVisible: isVisible, + bold: bold); + } + + protected static void AddGradient( + NBShaderRootItem rootItem, + ShaderGUIItem parent, + string label, + string countPropertyName, + string colorPrefix, + string alphaPrefix, + bool hdr = false, + Func isVisible = null) + { + new GradientItem( + rootItem, + parent, + countPropertyName, + 6, + BuildPropertyNames(colorPrefix, 6), + BuildPropertyNames(alphaPrefix, 3), + () => Content(label), + hdr, + ColorSpace.Gamma, + isVisible); + } + + protected static string[] BuildPropertyNames(string prefix, int count) + { + string[] names = new string[count]; + for (int i = 0; i < count; i++) + { + names[i] = prefix + i; + } + + return names; + } + + protected static bool IsPropertyMode(NBShaderRootItem rootItem, string propertyName, int expectedMode) + { + return rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) && + !info.Property.hasMixedValue && + Mathf.RoundToInt(info.Property.floatValue) == expectedMode; + } + + protected static bool IsPropertyMode(NBShaderRootItem rootItem, string propertyName, params int[] expectedModes) + { + if (!rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) || + info.Property.hasMixedValue) + { + return false; + } + + int value = Mathf.RoundToInt(info.Property.floatValue); + for (int i = 0; i < expectedModes.Length; i++) + { + if (value == expectedModes[i]) + { + return true; + } + } + + return false; + } + + internal static GUIContent Content(string label) + { + EnsureCacheLanguage(); + if (ContentCache.TryGetValue(label, out GUIContent cachedContent)) + { + return cachedContent; + } + + cachedContent = NBShaderInspectorLocalization.MakeInspectorContent("feature." + label, label); + ContentCache[label] = cachedContent; + return cachedContent; + } + + protected static GUIContent TillingContent() + { + return LocalizedInspectorContent(LocalizationTableName, "common.tilling", "Tilling"); + } + + protected static GUIContent OffsetContent() + { + return LocalizedInspectorContent(LocalizationTableName, "common.offset", "Offset"); + } + + internal static string Text(string key, string fallback) + { + return LocalizedText(LocalizationTableName, key, fallback); + } + + internal static string[] PopupOptions(string propertyName, string[] fallback) + { + EnsureCacheLanguage(); + if (PopupOptionsCache.TryGetValue(propertyName, out string[] cachedOptions)) + { + return cachedOptions; + } + + cachedOptions = NBShaderInspectorLocalization.GetInspectorOptions("feature.popup." + propertyName, fallback); + PopupOptionsCache[propertyName] = cachedOptions; + return cachedOptions; + } + + private static void EnsureCacheLanguage() + { + string currentLanguage = NBShaderInspectorLocalization.CurrentLanguage; + if (string.Equals(s_CacheLanguage, currentLanguage, StringComparison.Ordinal)) + { + return; + } + + s_CacheLanguage = currentLanguage; + ContentCache.Clear(); + PopupOptionsCache.Clear(); + } + + internal static bool IsTierKeywordAllowed(NBShaderRootItem rootItem, string keyword) + { + return string.IsNullOrEmpty(keyword) || + rootItem == null || + rootItem.Context == null || + rootItem.Context.IsKeywordAllowed(keyword); + } + + internal static Func TierVisible(NBShaderRootItem rootItem, string keyword, Func isVisible = null) + { + return () => IsTierKeywordAllowed(rootItem, keyword) && (isVisible == null || isVisible()); + } + } + + internal sealed class FeaturePopupItem : ShaderGUIPopUpItem + { + public FeaturePopupItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + Func contentProvider, + string[] popupNames, + Action onValueChanged = null, + Func isVisible = null, + string keyword = null) + : base( + rootItem, + parentItem, + propertyName, + contentProvider, + () => FeatureToggleFoldOutItem.PopupOptions(propertyName, popupNames), + onValueChanged, + string.IsNullOrEmpty(keyword) + ? isVisible + : FeatureToggleFoldOutItem.TierVisible(rootItem as NBShaderRootItem, keyword, isVisible)) + { + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureToggleFoldOutItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureToggleFoldOutItem.cs.meta new file mode 100644 index 00000000..acebd058 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FeatureToggleFoldOutItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 355bed04b23c4ea093ad45991f0004a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FresnelFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FresnelFeatureItem.cs new file mode 100644 index 00000000..1f922b5a --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FresnelFeatureItem.cs @@ -0,0 +1,50 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class FresnelFeatureItem : FeatureToggleFoldOutItem + { + private static readonly string[] FresnelModeNames = { "颜色", "透明" }; + + public FresnelFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_FresnelBlockFoldOut", "_fresnelEnabled", "菲涅尔", keyword: "_FRESNEL") + { + new NBShaderKeywordToggleItem( + rootItem, + this, + "_NB_Debug_Fresnel", + "NB_DEBUG_FRESNEL", + () => Content("菲涅尔测试颜色"), + isVisible: null); + new FeaturePopupItem(rootItem, this, "_FresnelMode", () => Content("菲涅尔模式"), FresnelModeNames, + property => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_FADE_ON, property.floatValue > 0.5f)); + Func isFresnelColorMode = () => IsPropertyMode(rootItem, "_FresnelMode", 0); + new ColorItem(rootItem, this, "_FresnelColor", () => Content("菲涅尔颜色"), isFresnelColorMode); + new VectorComponentItem(rootItem, this, "_FresnelUnit", 2, () => Content("菲涅尔强度"), true); + new VectorComponentItem(rootItem, this, "_FresnelUnit", 0, () => Content("菲涅尔位置"), true, -1f, 1f); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET, 0, () => Content("菲涅尔位置自定义曲线")); + new VectorComponentItem(rootItem, this, "_FresnelUnit", 1, () => Content("菲涅尔范围Pow"), true, 0f, 10f); + new VectorComponentItem(rootItem, this, "_FresnelUnit", 3, () => Content("菲涅尔硬度"), true); + new ToggleItem( + rootItem, + this, + "_InvertFresnel_Toggle", + () => Content("翻转菲涅尔"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON, enabled)); + new ToggleItem( + rootItem, + this, + "_FresnelColorAffectByAlpha", + () => Content("菲涅尔颜色受Alpha影响"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA, enabled), + isFresnelColorMode); + new VectorComponentItem(rootItem, this, "_FresnelRotation", 0, () => Content("菲涅尔方向偏移X"), false); + new VectorComponentItem(rootItem, this, "_FresnelRotation", 1, () => Content("菲涅尔方向偏移Y"), false); + new VectorComponentItem(rootItem, this, "_FresnelRotation", 2, () => Content("菲涅尔方向偏移Z"), false); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FresnelFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FresnelFeatureItem.cs.meta new file mode 100644 index 00000000..71bba83a --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/FresnelFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee140beb49b74735960d38a89bd528fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/MaskFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/MaskFeatureItem.cs new file mode 100644 index 00000000..9b1aafb1 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/MaskFeatureItem.cs @@ -0,0 +1,171 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class MaskFeatureItem : FeatureToggleFoldOutItem + { + private static readonly string[] TextureGradientNames = { "贴图", "渐变" }; + + public MaskFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_MaskBlockFoldOut", "_Mask_Toggle", "遮罩", keyword: "_MASKMAP_ON") + { + new NBShaderKeywordToggleItem( + rootItem, + this, + "_NB_Debug_Mask", + "NB_DEBUG_MASK", + () => Content("测试遮罩颜色"), + isVisible: null); + new VectorComponentItem(rootItem, this, "_MaskMapVec", 0, () => Content("遮罩强度"), true); + + PropertyToggleBlockItem refineBlock = ToggleBlock( + rootItem, + "_MaskRefineFoldOut", + "_MaskRefineToggle", + "遮罩整体调整", + NBShaderFlags.FLAG_BIT_PARTICLE_1_MASK_REFINE, + 1, + parent: this); + new VectorComponentItem(rootItem, refineBlock, "_MaskRefineVec", 0, () => Content("范围(Pow)"), false); + new VectorComponentItem(rootItem, refineBlock, "_MaskRefineVec", 1, () => Content("相乘"), false); + new VectorComponentItem(rootItem, refineBlock, "_MaskRefineVec", 2, () => Content("偏移(相加)"), false); + + new PNoiseBlendModeItem(rootItem, this, NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_MASK, "_MaskPNoiseBlendOpacity", () => Content("遮罩程序噪波混合"), + () => rootItem.Context.ProgramNoiseEnabled == MixedBool.True); + AddMaskMap(rootItem, this, "_MaskMap", "_MaskMapGradientToggle", "_MaskUVModeFoldOut", "遮罩", + NBShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP, + NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1, + NBShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP, + NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT, + 1, + "_MaskMapFoldOut"); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X, 0, () => Content("Mask图X轴偏移自定义曲线")); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y, 0, () => Content("Mask图Y轴偏移自定义曲线")); + new Vector2LineItem(rootItem, this, "_MaskMapOffsetAnition", true, () => Content("遮罩偏移速度")); + ShaderGUISliderItem maskMapUVRotationItem = new ShaderGUISliderItem(rootItem, this) + { + PropertyName = "_MaskMapUVRotation", + GuiContent = Content("遮罩旋转"), + Min = 0f, + Max = 360f + }; + maskMapUVRotationItem.InitTriggerByChild(); + PropertyToggleBlockItem rotateBlock = ToggleBlock( + rootItem, + "_MaskRotationFoldOut", + "_Mask_RotationToggle", + "遮罩旋转速度", + NBShaderFlags.FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON, + parent: this); + ShaderGUIFloatItem maskMapRotationSpeedItem = new ShaderGUIFloatItem(rootItem, rotateBlock) + { + PropertyName = "_MaskMapRotationSpeed", + GuiContent = Content("旋转速度") + }; + maskMapRotationSpeedItem.InitTriggerByChild(); + ShaderGUIItem maskNoiseAffect = new NoiseAffectItem(rootItem, this); + ShaderGUISliderItem maskDistortionIntensityItem = new ShaderGUISliderItem(rootItem, maskNoiseAffect) + { + PropertyName = "_MaskDistortion_intensity", + GuiContent = Content("遮罩扭曲强度"), + RangePropertyName = "MaskDistortionIntensityRangeVec" + }; + maskDistortionIntensityItem.InitTriggerByChild(); + + PropertyToggleBlockItem mask2Block = ToggleBlock( + rootItem, + "_Mask2BlockFoldOut", + "_Mask2_Toggle", + "遮罩2", + parent: this, + keyword: "_MASKMAP2_ON"); + AddMaskMap(rootItem, mask2Block, "_MaskMap2", "_MaskMap2GradientToggle", "_Mask2UVModeFoldOut", "遮罩2", + NBShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP2, + NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2, + NBShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP_2, + NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT, + 1); + new VectorComponentItem(rootItem, mask2Block, "_MaskMapVec", 1, () => Content("遮罩2旋转"), false); + new Vector2LineItem(rootItem, mask2Block, "_MaskMapOffsetAnition", false, () => Content("遮罩2偏移速度")); + + PropertyToggleBlockItem mask3Block = ToggleBlock( + rootItem, + "_Mask3BlockFoldOut", + "_Mask3_Toggle", + "遮罩3", + parent: this, + keyword: "_MASKMAP3_ON"); + AddMaskMap(rootItem, mask3Block, "_MaskMap3", "_MaskMap3GradientToggle", "_Mask3UVModeFoldOut", "遮罩3", + NBShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP3, + NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3, + NBShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP_3, + NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT, + 1); + new VectorComponentItem(rootItem, mask3Block, "_MaskMapVec", 2, () => Content("遮罩3旋转"), false); + new Vector2LineItem(rootItem, mask3Block, "_MaskMap3OffsetAnition", true, () => Content("遮罩3偏移速度")); + InitTriggerByChild(); + } + + private void AddMaskMap( + NBShaderRootItem rootItem, + ShaderGUIItem parent, + string texturePropertyName, + string modePropertyName, + string uvFoldOutPropertyName, + string label, + int wrapFlag, + int colorChannelFlagPos, + int uvModeFlagPos, + int gradientFlag, + int gradientFlagIndex, + string textureFoldOutPropertyName = null) + { + new FeaturePopupItem(rootItem, parent, modePropertyName, () => Content(label + "模式"), TextureGradientNames, + property => rootItem.SyncService.ApplyToggleFlag(gradientFlag, property.floatValue > 0.5f, gradientFlagIndex)); + ShaderGUIItem textureParent = parent; + if (string.IsNullOrEmpty(textureFoldOutPropertyName)) + { + AddTextureWithWrap(rootItem, parent, texturePropertyName, label + "贴图", wrapFlag, + isVisible: () => IsPropertyMode(rootItem, modePropertyName, 0)); + } + else + { + textureParent = AddTextureWithRelatedFoldOut(rootItem, parent, texturePropertyName, label + "贴图", textureFoldOutPropertyName, wrapFlag, + isVisible: () => IsPropertyMode(rootItem, modePropertyName, 0)); + } + + new ColorChannelSelectItem(rootItem, textureParent, colorChannelFlagPos, 0, () => Content(label + "通道选择"), + () => IsPropertyMode(rootItem, modePropertyName, 0)); + AddAlphaGradient(rootItem, parent, label + "渐变", texturePropertyName + "GradientCount", texturePropertyName + "GradientFloat", + () => IsPropertyMode(rootItem, modePropertyName, 1)); + new TextureScaleOffsetItem(rootItem, parent, texturePropertyName, false, () => IsPropertyMode(rootItem, modePropertyName, 1), TillingContent, OffsetContent); + new WrapModeItem(rootItem, parent, wrapFlag, () => Content(label + "UV Wrap"), 2, + () => IsPropertyMode(rootItem, modePropertyName, 1)); + new UVModeSelectItem(rootItem, parent, uvFoldOutPropertyName, uvModeFlagPos, 0, () => Content(label + "UV来源"), texturePropertyName, forceEnable: true); + } + + private static void AddAlphaGradient( + NBShaderRootItem rootItem, + ShaderGUIItem parent, + string label, + string countPropertyName, + string alphaPrefix, + Func isVisible = null) + { + new GradientItem( + rootItem, + parent, + countPropertyName, + 6, + Array.Empty(), + BuildPropertyNames(alphaPrefix, 3), + () => Content(label), + false, + ColorSpace.Gamma, + isVisible); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/MaskFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/MaskFeatureItem.cs.meta new file mode 100644 index 00000000..ccff8d2a --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/MaskFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5fe236301944650a35adc509015737c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/NoiseAndDistortFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/NoiseAndDistortFeatureItem.cs new file mode 100644 index 00000000..61cae800 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/NoiseAndDistortFeatureItem.cs @@ -0,0 +1,519 @@ +using System; +using System.Reflection; +using NBShader; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NBShaderEditor +{ + internal sealed class NoiseAndDistortFeatureItem : FeatureToggleFoldOutItem + { + private static readonly string[] DistortModeNames = { "FlowMap/RG贴图", "折射率" }; + private static readonly string[] ScreenDistortModeNames = { "No Screen Distort", "Deferred Distort", "Camera Opaque Distort" }; + private const int ScreenDistortModeDeferred = 1; + private const int ScreenDistortModeCameraOpaque = 2; + private const string ScreenDistortKeyword = "_SCREEN_DISTORT_MODE"; + private const string ScreenDistortModePropertyName = "_ScreenDistortModeToggle"; + private const string RendererDataListPropertyName = "m_RendererDataList"; + private const string LegacyRendererDataPropertyName = "m_RendererData"; + private const string RendererFeaturesPropertyName = "m_RendererFeatures"; + private const string OpaqueTexturePropertyName = "supportsCameraOpaqueTexture"; + private const string OpaqueTextureSerializedPropertyName = "m_RequireOpaqueTexture"; + private const string RendererFeatureActivePropertyName = "isActive"; + private const string RendererFeatureActiveSerializedPropertyName = "m_Active"; + private const string NBPostProcessTypeFullName = "NBShader.NBPostProcess"; + private const string NBPostProcessTypeName = "NBPostProcess"; + + public NoiseAndDistortFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_NoiseBlockFoldOut", "_noisemapEnabled", "扭曲", keyword: "_NOISEMAP") + { + new NBShaderKeywordToggleItem( + rootItem, + this, + "_NB_Debug_Distort", + "NB_DEBUG_DISTORT", + () => Content("扭曲强度值测试"), + isVisible: null); + ShaderGUISliderItem noiseIntensityItem = new ShaderGUISliderItem(rootItem, this) + { + PropertyName = "_NoiseIntensity", + GuiContent = Content("整体扭曲强度"), + RangePropertyName = "_NoiseIntensityRangeVec" + }; + noiseIntensityItem.InitTriggerByChild(); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY, 1, () => Content("扭曲强度自定义曲线")); + new FeaturePopupItem(rootItem, this, "_ScreenDistortModeToggle", () => Content("屏幕扰动模式"), ScreenDistortModeNames, + property => rootItem.SyncService.ApplyScreenDistortMode(Mathf.RoundToInt(property.floatValue)), + () => rootItem.Context.UIEffectEnabled != MixedBool.True, + ScreenDistortKeyword); + Func isDeferredDistortVisible = TierVisible( + rootItem, + ScreenDistortKeyword, + () => IsScreenDistortMode(rootItem, ScreenDistortModeDeferred)); + Func isCameraOpaqueDistortVisible = TierVisible( + rootItem, + ScreenDistortKeyword, + () => IsScreenDistortMode(rootItem, ScreenDistortModeCameraOpaque)); + Func isScreenDistortModeNeedsNBPostProcessVisible = () => isDeferredDistortVisible() || isCameraOpaqueDistortVisible(); + Func isMissingNBPostProcessVisible = () => isScreenDistortModeNeedsNBPostProcessVisible() && !HasActiveNBPostProcessRendererFeature(); + Func isMissingOpaqueTextureVisible = () => isCameraOpaqueDistortVisible() && !HasCameraOpaqueTextureCopyEnabled(); + new PingableHelpBoxItem( + rootItem, + this, + () => Text( + "feature.screenDistort.missingNbPostProcess.message", + "Screen Distort requires an active NB Post Process Feature on at least one RendererData in the current URP Pipeline Asset."), + MessageType.Warning, + () => ButtonContent("feature.screenDistort.pingRendererData", "Ping Renderer"), + GetRendererDataForNBPostProcessPing, + isMissingNBPostProcessVisible); + new PingableHelpBoxItem( + rootItem, + this, + () => Text( + "feature.screenDistort.missingOpaqueTextureCopy.message", + "Camera Opaque Distort requires Opaque Texture to be enabled on the current URP Pipeline Asset."), + MessageType.Warning, + () => ButtonContent("feature.screenDistort.pingPipelineAsset", "Ping URP Asset"), + GetCurrentRenderPipelineAsset, + isMissingOpaqueTextureVisible); + ShaderGUISliderItem screenDistortIntensityItem = new ShaderGUISliderItem( + rootItem, + this, + TierVisible( + rootItem, + ScreenDistortKeyword, + () => rootItem.Context.UIEffectEnabled != MixedBool.True && IsPropertyGreater(rootItem, "_ScreenDistortModeToggle", 0.5f))) + { + PropertyName = "_ScreenDistortIntensity", + GuiContent = Content("屏幕扭曲强度"), + RangePropertyName = "_ScreenDistortIntensityRangeVec" + }; + screenDistortIntensityItem.InitTriggerByChild(); + new ToggleItem( + rootItem, + this, + "_DisableMainPassToggle", + () => Content("关闭主材质Pass"), + enabled => + { + rootItem.SyncService.ApplyScreenDistortMode(GetIntProperty(rootItem, "_ScreenDistortModeToggle")); + }, + TierVisible( + rootItem, + ScreenDistortKeyword, + () => rootItem.Context.UIEffectEnabled != MixedBool.True && IsPropertyGreater(rootItem, "_ScreenDistortModeToggle", 0.5f))); + + PropertyToggleBlockItem screenAlphaBlock = ToggleBlock( + rootItem, + "_ScreenDistortAlphaFoldOut", + "_ScreenDistortAlphaRefineToggle", + "屏幕扭曲Alpha整体调整", + NBShaderFlags.FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE, + 1, + parent: this, + isVisible: TierVisible( + rootItem, + ScreenDistortKeyword, + () => rootItem.Context.UIEffectEnabled != MixedBool.True && IsPropertyGreater(rootItem, "_ScreenDistortModeToggle", 0.5f))); + ShaderGUIFloatItem screenDistortAlphaPowItem = new ShaderGUIFloatItem(rootItem, screenAlphaBlock) + { + PropertyName = "_ScreenDistortAlphaPow", + GuiContent = Content("范围(Pow)") + }; + screenDistortAlphaPowItem.InitTriggerByChild(); + ShaderGUIFloatItem screenDistortAlphaMultiItem = new ShaderGUIFloatItem(rootItem, screenAlphaBlock) + { + PropertyName = "_ScreenDistortAlphaMulti", + GuiContent = Content("相乘") + }; + screenDistortAlphaMultiItem.InitTriggerByChild(); + ShaderGUIFloatItem screenDistortAlphaAddItem = new ShaderGUIFloatItem(rootItem, screenAlphaBlock) + { + PropertyName = "_ScreenDistortAlphaAdd", + GuiContent = Content("偏移(相加)") + }; + screenDistortAlphaAddItem.InitTriggerByChild(); + + new FeaturePopupItem(rootItem, this, "_DistortMode", () => Content("扭曲模式"), DistortModeNames, + property => rootItem.SyncService.ApplyToggleKeyword("_DISTORT_REFRACTION", property.floatValue > 0.5f), + keyword: "_DISTORT_REFRACTION"); + TextureRelatedFoldOutItem noiseMapRelatedFoldOut = AddTextureWithRelatedFoldOut(rootItem, this, "_NoiseMap", "扭曲贴图", "_NoiseMapFoldOut", NBShaderFlags.FLAG_BIT_WRAPMODE_NOISEMAP, + isVisible: () => IsPropertyMode(rootItem, "_DistortMode", 0)); + new UVModeSelectItem(rootItem, noiseMapRelatedFoldOut, "_NoiseUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_NOISE_MAP, 0, () => Content("扭曲贴图UV来源"), "_NoiseMap", + isVisible: () => IsPropertyMode(rootItem, "_DistortMode", 0)); + new Vector2LineItem(rootItem, noiseMapRelatedFoldOut, "_DistortionDirection", true, () => Content("扭曲方向强度"), () => IsPropertyMode(rootItem, "_DistortMode", 0)); + new CustomDataSelectItem(rootItem, noiseMapRelatedFoldOut, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X, 2, () => Content("扭曲方向强度X自定义曲线"), () => IsPropertyMode(rootItem, "_DistortMode", 0)); + new CustomDataSelectItem(rootItem, noiseMapRelatedFoldOut, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y, 2, () => Content("扭曲方向强度Y自定义曲线"), () => IsPropertyMode(rootItem, "_DistortMode", 0)); + ShaderGUISliderItem noiseMapUVRotationItem = new ShaderGUISliderItem(rootItem, noiseMapRelatedFoldOut, () => IsPropertyMode(rootItem, "_DistortMode", 0)) + { + PropertyName = "_NoiseMapUVRotation", + GuiContent = Content("扭曲旋转"), + Min = 0f, + Max = 360f + }; + noiseMapUVRotationItem.InitTriggerByChild(); + new Vector2LineItem(rootItem, noiseMapRelatedFoldOut, "_NoiseOffset", true, () => Content("扭曲偏移速度"), () => IsPropertyMode(rootItem, "_DistortMode", 0)); + new ToggleItem( + rootItem, + noiseMapRelatedFoldOut, + "_DistortionBothDirection_Toggle", + () => Content("0.5为中值,双向扭曲"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON, enabled), + () => IsPropertyMode(rootItem, "_DistortMode", 0)); + ShaderGUISliderItem refractionIorItem = new ShaderGUISliderItem( + rootItem, + this, + TierVisible(rootItem, "_DISTORT_REFRACTION", () => IsPropertyMode(rootItem, "_DistortMode", 1))) + { + PropertyName = "_RefractionIOR", + GuiContent = Content("折射率"), + Min = 0f, + Max = 5f + }; + refractionIorItem.InitTriggerByChild(); + new PNoiseBlendModeItem(rootItem, this, NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT, "_DistortPNoiseBlendOpacity", () => Content("扭曲程序噪波混合"), + () => rootItem.Context.ProgramNoiseEnabled == MixedBool.True); + + PropertyToggleBlockItem noiseMaskBlock = ToggleBlock( + rootItem, + "_NoiseMaskBlockFoldOut", + "_noiseMaskMap_Toggle", + "扭曲遮罩", + parent: this, + keyword: "_NOISE_MASKMAP"); + AddTextureWithWrap(rootItem, noiseMaskBlock, "_NoiseMaskMap", "扭曲遮罩贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_NOISE_MASKMAP); + new ColorChannelSelectItem(rootItem, noiseMaskBlock, NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK, 0, () => Content("扭曲遮罩图通道选择")); + new UVModeSelectItem(rootItem, noiseMaskBlock, "_NoiseMaskUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP, 0, () => Content("扭曲遮罩贴图UV来源"), "_NoiseMaskMap"); + + InitTriggerByChild(); + } + + private static int GetIntProperty(NBShaderRootItem rootItem, string propertyName) + { + return rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) && !info.Property.hasMixedValue + ? Mathf.RoundToInt(info.Property.floatValue) + : 0; + } + + private static bool IsPropertyGreater(NBShaderRootItem rootItem, string propertyName, float threshold) + { + return rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) && + !info.Property.hasMixedValue && + info.Property.floatValue > threshold; + } + + private static bool IsScreenDistortMode(NBShaderRootItem rootItem, int mode) + { + return rootItem.Context.UIEffectEnabled != MixedBool.True && + IsPropertyMode(rootItem, ScreenDistortModePropertyName, mode); + } + + private static bool HasActiveNBPostProcessRendererFeature() + { + try + { + RenderPipelineAsset pipelineAsset = GetCurrentRenderPipelineAsset(); + if (pipelineAsset == null) + { + return false; + } + + SerializedObject pipelineObject = new SerializedObject(pipelineAsset); + SerializedProperty rendererDataList = pipelineObject.FindProperty(RendererDataListPropertyName); + if (rendererDataList != null && rendererDataList.isArray) + { + for (int i = 0; i < rendererDataList.arraySize; i++) + { + UnityEngine.Object rendererData = rendererDataList.GetArrayElementAtIndex(i).objectReferenceValue; + if (RendererDataHasNBPostProcess(rendererData, requireActive: true)) + { + return true; + } + } + + return false; + } + + SerializedProperty legacyRendererData = pipelineObject.FindProperty(LegacyRendererDataPropertyName); + return legacyRendererData != null && RendererDataHasNBPostProcess(legacyRendererData.objectReferenceValue, requireActive: true); + } + catch (Exception) + { + return false; + } + } + + private static bool RendererDataHasNBPostProcess(UnityEngine.Object rendererData, bool requireActive) + { + if (rendererData == null) + { + return false; + } + + SerializedObject rendererDataObject = new SerializedObject(rendererData); + SerializedProperty rendererFeatures = rendererDataObject.FindProperty(RendererFeaturesPropertyName); + if (rendererFeatures == null || !rendererFeatures.isArray) + { + return false; + } + + for (int i = 0; i < rendererFeatures.arraySize; i++) + { + UnityEngine.Object rendererFeature = rendererFeatures.GetArrayElementAtIndex(i).objectReferenceValue; + if (IsNBPostProcessFeature(rendererFeature) && + (!requireActive || IsRendererFeatureActive(rendererFeature))) + { + return true; + } + } + + return false; + } + + private static bool IsNBPostProcessFeature(UnityEngine.Object rendererFeature) + { + if (rendererFeature == null) + { + return false; + } + + for (Type type = rendererFeature.GetType(); type != null; type = type.BaseType) + { + if (string.Equals(type.FullName, NBPostProcessTypeFullName, StringComparison.Ordinal) || + string.Equals(type.Name, NBPostProcessTypeName, StringComparison.Ordinal)) + { + return true; + } + } + + return false; + } + + private static bool IsRendererFeatureActive(UnityEngine.Object rendererFeature) + { + if (rendererFeature == null) + { + return false; + } + + if (TryGetBoolProperty(rendererFeature, RendererFeatureActivePropertyName, out bool isActive)) + { + return isActive; + } + + try + { + SerializedObject rendererFeatureObject = new SerializedObject(rendererFeature); + SerializedProperty activeProperty = rendererFeatureObject.FindProperty(RendererFeatureActiveSerializedPropertyName); + return activeProperty != null && + activeProperty.propertyType == SerializedPropertyType.Boolean && + activeProperty.boolValue; + } + catch (Exception) + { + return false; + } + } + + private static bool HasCameraOpaqueTextureCopyEnabled() + { + try + { + RenderPipelineAsset pipelineAsset = GetCurrentRenderPipelineAsset(); + if (pipelineAsset == null) + { + return false; + } + + if (TryGetBoolProperty(pipelineAsset, OpaqueTexturePropertyName, out bool supportsCameraOpaqueTexture)) + { + return supportsCameraOpaqueTexture; + } + + SerializedObject pipelineObject = new SerializedObject(pipelineAsset); + SerializedProperty opaqueTextureProperty = pipelineObject.FindProperty(OpaqueTextureSerializedPropertyName); + return opaqueTextureProperty != null && + opaqueTextureProperty.propertyType == SerializedPropertyType.Boolean && + opaqueTextureProperty.boolValue; + } + catch (Exception) + { + return false; + } + } + + private static UnityEngine.Object GetRendererDataForNBPostProcessPing() + { + try + { + RenderPipelineAsset pipelineAsset = GetCurrentRenderPipelineAsset(); + if (pipelineAsset == null) + { + return null; + } + + SerializedObject pipelineObject = new SerializedObject(pipelineAsset); + SerializedProperty rendererDataList = pipelineObject.FindProperty(RendererDataListPropertyName); + if (rendererDataList != null && rendererDataList.isArray) + { + return GetRendererDataForNBPostProcessPing(rendererDataList); + } + + SerializedProperty legacyRendererData = pipelineObject.FindProperty(LegacyRendererDataPropertyName); + return legacyRendererData != null ? legacyRendererData.objectReferenceValue : null; + } + catch (Exception) + { + return null; + } + } + + private static UnityEngine.Object GetRendererDataForNBPostProcessPing(SerializedProperty rendererDataList) + { + UnityEngine.Object firstRendererData = null; + UnityEngine.Object rendererDataWithInactiveFeature = null; + for (int i = 0; i < rendererDataList.arraySize; i++) + { + UnityEngine.Object rendererData = rendererDataList.GetArrayElementAtIndex(i).objectReferenceValue; + if (rendererData == null) + { + continue; + } + + if (firstRendererData == null) + { + firstRendererData = rendererData; + } + + if (RendererDataHasNBPostProcess(rendererData, requireActive: true)) + { + return rendererData; + } + + if (rendererDataWithInactiveFeature == null && + RendererDataHasNBPostProcess(rendererData, requireActive: false)) + { + rendererDataWithInactiveFeature = rendererData; + } + } + + return rendererDataWithInactiveFeature != null ? rendererDataWithInactiveFeature : firstRendererData; + } + + private static RenderPipelineAsset GetCurrentRenderPipelineAsset() + { + return QualitySettings.renderPipeline != null + ? QualitySettings.renderPipeline + : GraphicsSettings.currentRenderPipeline; + } + + private static bool TryGetBoolProperty(UnityEngine.Object target, string propertyName, out bool value) + { + value = false; + if (target == null) + { + return false; + } + + try + { + PropertyInfo propertyInfo = target.GetType().GetProperty( + propertyName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + if (propertyInfo == null || propertyInfo.PropertyType != typeof(bool)) + { + return false; + } + + value = (bool)propertyInfo.GetValue(target, null); + return true; + } + catch (Exception) + { + return false; + } + } + + private static GUIContent ButtonContent(string key, string fallback) + { + return NBShaderInspectorLocalization.MakeContent("inspector." + key + ".button", fallback); + } + + private sealed class PingableHelpBoxItem : ShaderGUIItem + { + private const float HelpBoxPadding = 6f; + private const float HelpBoxButtonGap = 4f; + private const float MaxButtonWidth = 160f; + private static readonly GUIContent TempHelpContent = new GUIContent(); + + private readonly Func _messageProvider; + private readonly MessageType _messageType; + private readonly Func _buttonContentProvider; + private readonly Func _targetProvider; + private readonly Func _isVisible; + + public PingableHelpBoxItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + Func messageProvider, + MessageType messageType, + Func buttonContentProvider, + Func targetProvider, + Func isVisible) : base(rootItem, parentItem) + { + _messageProvider = messageProvider ?? (() => string.Empty); + _messageType = messageType; + _buttonContentProvider = buttonContentProvider ?? (() => GUIContent.none); + _targetProvider = targetProvider ?? (() => null); + _isVisible = isVisible; + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + using (ParentControlDisabledScope()) + { + string message = _messageProvider(); + GUIContent buttonContent = _buttonContentProvider(); + TempHelpContent.text = message; + float width = Mathf.Max(1f, EditorGUIUtility.currentViewWidth + GlobalRectWidthExpansion + GlobalRectXOffset); + float messageHeight = Mathf.Max( + EditorGUIUtility.singleLineHeight * 2f, + EditorStyles.helpBox.CalcHeight(TempHelpContent, width)); + float buttonHeight = EditorGUIUtility.singleLineHeight; + float height = messageHeight + HelpBoxButtonGap + buttonHeight + HelpBoxPadding; + Rect rect = ApplyGlobalRectCompensation(LayoutRect(height)); + EditorGUI.HelpBox(rect, message, _messageType); + + float buttonWidth = Mathf.Min( + MaxButtonWidth, + Mathf.Max(90f, EditorStyles.miniButton.CalcSize(buttonContent).x + 18f)); + buttonWidth = Mathf.Min(buttonWidth, Mathf.Max(0f, rect.width - HelpBoxPadding * 2f)); + Rect buttonRect = new Rect( + rect.xMax - HelpBoxPadding - buttonWidth, + rect.yMax - HelpBoxPadding - buttonHeight, + buttonWidth, + buttonHeight); + + UnityEngine.Object target = _targetProvider(); + using (new EditorGUI.DisabledScope(target == null)) + { + if (GUI.Button(buttonRect, buttonContent, EditorStyles.miniButton)) + { + Selection.activeObject = target; + EditorGUIUtility.PingObject(target); + } + } + + TempHelpContent.text = string.Empty; + } + } + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/NoiseAndDistortFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/NoiseAndDistortFeatureItem.cs.meta new file mode 100644 index 00000000..9eb099d7 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/NoiseAndDistortFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e4f64374c74c47478edfdd0ddb6e8355 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ParallaxFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ParallaxFeatureItem.cs new file mode 100644 index 00000000..c1fa5a2d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ParallaxFeatureItem.cs @@ -0,0 +1,35 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class ParallaxFeatureItem : FeatureToggleFoldOutItem + { + public ParallaxFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_ParallaxBlockFoldOut", "_ParallaxMapping_Toggle", "遮蔽视差", keyword: "_PARALLAX_MAPPING", isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True) + { + AddTextureWithWrap(rootItem, this, "_ParallaxMapping_Map", "视差贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP); + ShaderGUISliderItem parallaxMappingIntensityItem = new ShaderGUISliderItem(rootItem, this) + { + PropertyName = "_ParallaxMapping_Intensity", + GuiContent = Content("视差"), + RangePropertyName = "_ParallaxMapping_IntensityRangeVec" + }; + parallaxMappingIntensityItem.InitTriggerByChild(); + new VectorComponentItem(rootItem, this, "_ParallaxMapping_Vec", 0, () => Content("遮蔽视差最小层数"), true, 0f, 100f); + new VectorComponentItem(rootItem, this, "_ParallaxMapping_Vec", 1, () => Content("遮蔽视差最大层数"), true, 0f, 100f); + new HelpBoxItem(rootItem, this, () => Text("feature.parallax.layerWarning.message", "遮蔽视差层数过高将影响性能"), MessageType.Warning, + () => IsParallaxMaxLayerHigh(rootItem)); + InitTriggerByChild(); + } + + private static bool IsParallaxMaxLayerHigh(NBShaderRootItem rootItem) + { + return rootItem.PropertyInfoDic.TryGetValue("_ParallaxMapping_Vec", out ShaderPropertyInfo info) && + !info.Property.hasMixedValue && + info.Property.vectorValue.y >= 20f; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ParallaxFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ParallaxFeatureItem.cs.meta new file mode 100644 index 00000000..4f749b23 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ParallaxFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d5bf38ca73454cc1916d18f40182d5ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/PortalFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/PortalFeatureItem.cs new file mode 100644 index 00000000..3e315503 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/PortalFeatureItem.cs @@ -0,0 +1,17 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class PortalFeatureItem : FeatureToggleFoldOutItem + { + public PortalFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_PortalBlockFoldOut", "_Portal_Toggle", "模板视差", onValueChanged: _ => rootItem.SyncService.ApplyPortalState(), isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True) + { + new ToggleItem(rootItem, this, "_Portal_MaskToggle", () => Content("模板视差蒙版"), _ => rootItem.SyncService.ApplyPortalState()); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/PortalFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/PortalFeatureItem.cs.meta new file mode 100644 index 00000000..a7d95858 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/PortalFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 67c4fd7f472848dfbefe5703bb834b60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ProgramNoiseFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ProgramNoiseFeatureItem.cs new file mode 100644 index 00000000..f2787740 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ProgramNoiseFeatureItem.cs @@ -0,0 +1,58 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class ProgramNoiseFeatureItem : FeatureToggleFoldOutItem + { + public ProgramNoiseFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_ProgramNoiseBlockFoldOut", "_ProgramNoise_Toggle", "程序化噪波", keyword: "_PROGRAM_NOISE") + { + new NBShaderKeywordToggleItem( + rootItem, + this, + "_NB_Debug_PNoise", + "NB_DEBUG_PNOISE", + () => Content("程序化噪波测试颜色"), + isVisible: null); + new UVModeSelectItem(rootItem, this, "_ProgramNoiseUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE, 0, () => Content("程序噪波UV来源"), forceEnable: true); + ShaderGUIFloatItem programNoiseRotateItem = new ShaderGUIFloatItem(rootItem, this) + { + PropertyName = "_ProgramNoise_Rotate", + GuiContent = Content("程序化噪波旋转") + }; + programNoiseRotateItem.InitTriggerByChild(); + + PropertyToggleBlockItem simpleBlock = ToggleBlock(rootItem, "_ProgramNoiseSimpleFoldOut", "_ProgramNoise_Simple_Toggle", "Perlin噪波", + parent: this, keyword: "_PROGRAM_NOISE_SIMPLE"); + new Vector2LineItem(rootItem, simpleBlock, "_DissolveVoronoi_Vec", true, () => Content("噪波1缩放")); + new VectorComponentItem(rootItem, simpleBlock, "_DissolveVoronoi_Vec2", 2, () => Content("噪波1速度"), false); + new Vector2LineItem(rootItem, simpleBlock, "_DissolveVoronoi_Vec4", true, () => Content("噪波1偏移")); + new Vector2LineItem(rootItem, simpleBlock, "_DissolveVoronoi_Vec3", true, () => Content("噪波1偏移速度")); + new CustomDataSelectItem(rootItem, simpleBlock, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X, 2, () => Content("噪波1偏移速度X自定义曲线")); + new CustomDataSelectItem(rootItem, simpleBlock, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y, 2, () => Content("噪波1偏移速度Y自定义曲线")); + + PropertyToggleBlockItem voronoiBlock = ToggleBlock(rootItem, "_ProgramNoiseVoronoiFoldOut", "_ProgramNoise_Voronoi_Toggle", "Voronoi噪波", + parent: this, keyword: "_PROGRAM_NOISE_VORONOI"); + new Vector2LineItem(rootItem, voronoiBlock, "_DissolveVoronoi_Vec", false, () => Content("噪波2缩放")); + new VectorComponentItem(rootItem, voronoiBlock, "_DissolveVoronoi_Vec2", 3, () => Content("噪波2速度"), false); + new Vector2LineItem(rootItem, voronoiBlock, "_DissolveVoronoi_Vec4", false, () => Content("噪波2偏移")); + new Vector2LineItem(rootItem, voronoiBlock, "_DissolveVoronoi_Vec3", false, () => Content("噪波2偏移速度")); + new CustomDataSelectItem(rootItem, voronoiBlock, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X, 2, () => Content("噪波2偏移速度X自定义曲线")); + new CustomDataSelectItem(rootItem, voronoiBlock, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y, 2, () => Content("噪波2偏移速度Y自定义曲线")); + new VectorComponentItem(rootItem, this, "_DissolveVoronoi_Vec2", 0, () => Content("噪波1和噪波2混合系数"), true); + new PNoiseBlendModeItem( + rootItem, + this, + NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND, + "_ProgramNoiseBaseBlendOpacity", + () => Content("两种程序噪波混合"), + () => rootItem.Context.ProgramNoiseEnabled == MixedBool.True && + rootItem.Context.IsToggleOn("_ProgramNoise_Simple_Toggle") && + rootItem.Context.IsToggleOn("_ProgramNoise_Voronoi_Toggle")); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ProgramNoiseFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ProgramNoiseFeatureItem.cs.meta new file mode 100644 index 00000000..724e4851 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/ProgramNoiseFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c6a446a2f0364fb0844cb9d36bd39a27 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/RampColorFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/RampColorFeatureItem.cs new file mode 100644 index 00000000..c8fb8197 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/RampColorFeatureItem.cs @@ -0,0 +1,37 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class RampColorFeatureItem : FeatureToggleFoldOutItem + { + private static readonly string[] RampSourceNames = { "渐变", "贴图" }; + private static readonly string[] BlendModeNames = { "叠加", "相乘" }; + + public RampColorFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_RampColorBlockFoldOut", "_RampColorToggle", "颜色映射(Ramp)", keyword: "_COLOR_RAMP") + { + Func isRampMapVisible = TierVisible(rootItem, "_COLOR_RAMP_MAP", () => IsPropertyMode(rootItem, "_RampColorSourceMode", 1)); + new FeaturePopupItem(rootItem, this, "_RampColorSourceMode", () => Content("Ramp来源模式"), RampSourceNames, + _ => rootItem.SyncService.SyncMaterialState(), + keyword: "_COLOR_RAMP_MAP"); + AddTextureWithWrap(rootItem, this, "_RampColorMap", "颜色映射黑白图", NBShaderFlags.FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP, + isVisible: isRampMapVisible); + new TextureScaleOffsetItem(rootItem, this, "_RampColorMap", false, () => IsPropertyMode(rootItem, "_RampColorSourceMode", 0), TillingContent, OffsetContent); + new WrapModeItem(rootItem, this, NBShaderFlags.FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP, () => Content("颜色映射UV Wrap"), 2, + () => IsPropertyMode(rootItem, "_RampColorSourceMode", 0)); + new ColorChannelSelectItem(rootItem, this, NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP, 0, () => Content("颜色映射黑白图通道选择"), + isRampMapVisible); + new UVModeSelectItem(rootItem, this, "_RampColorUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP, 0, () => Content("颜色映射黑白图UV来源"), "_RampColorMap", true); + new Vector2LineItem(rootItem, this, "_RampColorMapOffset", true, () => Content("颜色映射贴图偏移速度")); + new VectorComponentItem(rootItem, this, "_RampColorMapOffset", 3, () => Content("颜色映射贴图旋转"), true, 0f, 360f); + AddGradient(rootItem, this, "映射颜色", "_RampColorCount", "_RampColor", "_RampColorAlpha", hdr: true); + new FeaturePopupItem(rootItem, this, "_RampColorBlendMode", () => Content("Ramp颜色混合模式"), BlendModeNames, + property => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD, property.floatValue > 0.5f)); + new ColorItem(rootItem, this, "_RampColorBlendColor", () => Content("颜色映射叠加颜色")); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/RampColorFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/RampColorFeatureItem.cs.meta new file mode 100644 index 00000000..d3785ce8 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/RampColorFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45dcb7c7a750440a99a8d5017d41fa22 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/SharedUVFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/SharedUVFeatureItem.cs new file mode 100644 index 00000000..49aaeb93 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/SharedUVFeatureItem.cs @@ -0,0 +1,24 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class SharedUVFeatureItem : FeatureToggleFoldOutItem + { + public SharedUVFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_SharedUVBlockFoldOut", "_SharedUVToggle", "公共UV", keyword: "_SHARED_UV") + { + new UVModeSelectItem(rootItem, this, "_SharedUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_SHAREDUV, 0, () => Content("公共UV来源"), forceEnable: true); + new Vector2LineItem(rootItem, this, "_SharedUV_ST", true, () => Content("公共UV Tiling")); + new Vector2LineItem(rootItem, this, "_SharedUV_ST", false, () => Content("公共UV Offset")); + new Vector2LineItem(rootItem, this, "_SharedUV_Vec", true, () => Content("公共UV偏移速度")); + new VectorComponentItem(rootItem, this, "_SharedUV_Vec", 2, () => Content("旋转"), false); + new VectorComponentItem(rootItem, this, "_SharedUV_Vec", 3, () => Content("旋转速度"), false); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X, 3, () => Content("公共UV X轴偏移自定义曲线")); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y, 3, () => Content("公共UV Y轴偏移自定义曲线")); + InitTriggerByChild(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/SharedUVFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/SharedUVFeatureItem.cs.meta new file mode 100644 index 00000000..266f8c02 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/SharedUVFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dece160aaa274dd79c1e771fed834249 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VatFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VatFeatureItem.cs new file mode 100644 index 00000000..097246e1 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VatFeatureItem.cs @@ -0,0 +1,428 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class VatFeatureItem : FeatureToggleFoldOutItem + { + private static readonly string[] VatModeNames = { "Houdini", "TyFlow" }; + private static readonly string[] HoudiniVatSubModeNames = + { + "SoftBody (Deformation)", + "RigidBody (Pieces)", + "Dynamic Remeshing (Lookup)", + "Particle Sprites (Billboard)" + }; + private static readonly string[] TyFlowVatSubModeNames = + { + "Absolute positions", + "Relative offsets", + "Skin (R)", + "Skin (PR)", + "Skin (PRSAVE)", + "Skin (PRSXYZ)" + }; + + public VatFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_VATBlockFoldOut", "_VAT_Toggle", "VAT顶点动画图", keyword: "_VAT", onValueChanged: rootItem.SyncService.ApplyVatEnabled) + { + new FeaturePopupItem(rootItem, this, "_VATMode", () => Content("VAT模式"), VatModeNames, _ => rootItem.SyncService.SyncMaterialState()); + Func isHoudini = () => IsPropertyMode(rootItem, "_VATMode", (int)VATMode.Houdini); + Func isTyflow = () => IsPropertyMode(rootItem, "_VATMode", (int)VATMode.Tyflow); + Func hasVatFrameCustomData = () => IsVatFrameCustomDataVisible(rootItem); + ShaderGUIFloatItem floatItem; + + new FeaturePopupItem(rootItem, this, "_HoudiniVATSubMode", () => Content("Houdini VAT Sub Mode"), HoudiniVatSubModeNames, + _ => rootItem.SyncService.SyncMaterialState(), isHoudini); + new HelpBoxItem(rootItem, this, () => Text("feature.vat.houdiniUnsupportedParticle.message", "该 Houdini VAT 类型需要 Mesh 多 UV 数据,不支持 ParticleSystem VertexStream 模式。"), MessageType.Warning, + () => isHoudini() && HasUnsupportedHoudiniParticleMode(rootItem)); + new SectionLabelItem(rootItem, this, () => Content("Playback"), isHoudini); + new ToggleItem(rootItem, this, "_B_autoPlayback", () => Content("Auto Playback"), isVisible: isHoudini); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && ShouldDrawWhenFloatOff(rootItem, "_B_autoPlayback")) + { + PropertyName = "_displayFrame", + GuiContent = Content("Display Frame") + }; + floatItem.InitTriggerByChild(); + new VatFrameCustomDataItem(rootItem, this, () => Content("VAT Frame CustomData"), () => isHoudini() && hasVatFrameCustomData(), hasVatFrameCustomData); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_gameTimeAtFirstFrame", + GuiContent = Content("Game Time at First Frame") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_playbackSpeed", + GuiContent = Content("Playback Speed") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_houdiniFPS", + GuiContent = Content("Houdini FPS") + }; + floatItem.InitTriggerByChild(); + new ToggleItem(rootItem, this, "_B_interpolate", () => Content("Interframe Interpolation"), isVisible: isHoudini); + new ToggleItem(rootItem, this, "_animateFirstFrame", () => Content("Animate First Frame"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 1)); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_frameCount", + GuiContent = Content("Frame Count") + }; + floatItem.InitTriggerByChild(); + + new SectionLabelItem(rootItem, this, () => Content("Bounds Metadata"), isHoudini); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_boundMinX", + GuiContent = Content("Bound Min X") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_boundMinY", + GuiContent = Content("Bound Min Y") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_boundMinZ", + GuiContent = Content("Bound Min Z") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_boundMaxX", + GuiContent = Content("Bound Max X") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_boundMaxY", + GuiContent = Content("Bound Max Y") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini) + { + PropertyName = "_boundMaxZ", + GuiContent = Content("Bound Max Z") + }; + floatItem.InitTriggerByChild(); + + new SectionLabelItem(rootItem, this, () => Content("Textures"), isHoudini); + new TextureItem(rootItem, this, "_posTexture", () => Content("Position Texture"), drawScaleOffset: false, isVisible: isHoudini); + new TextureItem(rootItem, this, "_posTexture2", () => Content("Position Texture 2"), drawScaleOffset: false, + isVisible: () => isHoudini() && ShouldDrawWhenFloatOn(rootItem, "_B_LOAD_POS_TWO_TEX")); + new TextureItem(rootItem, this, "_rotTexture", () => Content("Rotation Texture"), drawScaleOffset: false, + isVisible: () => isHoudini() && ShouldDrawHoudiniRotationTexture(rootItem)); + new TextureItem(rootItem, this, "_colTexture", () => Content("Color Texture"), drawScaleOffset: false, + isVisible: () => isHoudini() && ShouldDrawWhenFloatOn(rootItem, "_B_LOAD_COL_TEX")); + new TextureItem(rootItem, this, "_lookupTable", () => Content("Lookup Table"), drawScaleOffset: false, + isVisible: () => isHoudini() && (IsPropertyMode(rootItem, "_HoudiniVATSubMode", 2) || ShouldDrawWhenFloatOn(rootItem, "_B_LOAD_LOOKUP_TABLE"))); + + new SectionLabelItem(rootItem, this, () => Content("Scale"), () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 1, 3)); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 1, 3)) + { + PropertyName = "_globalPscaleMul", + GuiContent = Content("Global Piece Scale Multiplier") + }; + floatItem.InitTriggerByChild(); + new ToggleItem(rootItem, this, "_B_pscaleAreInPosA", () => Content("Piece Scales in Position Alpha"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 1, 3)); + + new SectionLabelItem(rootItem, this, () => Content("Particle Sprite"), () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3)); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3)) + { + PropertyName = "_widthBaseScale", + GuiContent = Content("Width Base Scale") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3)) + { + PropertyName = "_heightBaseScale", + GuiContent = Content("Height Base Scale") + }; + floatItem.InitTriggerByChild(); + new ToggleItem(rootItem, this, "_B_hideOverlappingOrigin", () => Content("Hide Overlapping Origin"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3)); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3) && ShouldDrawWhenFloatOn(rootItem, "_B_hideOverlappingOrigin")) + { + PropertyName = "_originRadius", + GuiContent = Content("Origin Effective Radius") + }; + floatItem.InitTriggerByChild(); + new ToggleItem(rootItem, this, "_B_CAN_SPIN", () => Content("Particles Can Spin"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3)); + new ToggleItem(rootItem, this, "_B_spinFromHeading", () => Content("Compute Spin from Heading"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3) && ShouldDrawWhenFloatOn(rootItem, "_B_CAN_SPIN")); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3) && ShouldDrawWhenFloatOn(rootItem, "_B_CAN_SPIN") && ShouldDrawWhenFloatOff(rootItem, "_B_spinFromHeading")) + { + PropertyName = "_spinPhase", + GuiContent = Content("Particle Spin Phase") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3) && ShouldDrawWhenFloatOn(rootItem, "_B_CAN_SPIN")) + { + PropertyName = "_scaleByVelAmount", + GuiContent = Content("Scale by Velocity Amount") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3)) + { + PropertyName = "_particleTexUScale", + GuiContent = Content("Particle Texture U Scale") + }; + floatItem.InitTriggerByChild(); + floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3)) + { + PropertyName = "_particleTexVScale", + GuiContent = Content("Particle Texture V Scale") + }; + floatItem.InitTriggerByChild(); + + new SectionLabelItem(rootItem, this, () => Content("Flags"), isHoudini); + new ToggleItem(rootItem, this, "_B_LOAD_POS_TWO_TEX", () => Content("Positions Require Two Textures"), isVisible: isHoudini); + new ToggleItem(rootItem, this, "_B_UNLOAD_ROT_TEX", () => Content("Use Compressed Normals (no rotTex)"), isVisible: () => isHoudini() && ShouldDrawCompressedNormalsToggle(rootItem)); + new ToggleItem(rootItem, this, "_B_LOAD_COL_TEX", () => Content("Load Color Texture"), isVisible: isHoudini); + new ToggleItem(rootItem, this, "_B_LOAD_LOOKUP_TABLE", () => Content("Load Lookup Table"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 2)); + + new TextureItem(rootItem, this, "_VATTex", () => Content("VAT texture"), drawScaleOffset: false, isVisible: isTyflow); + floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow) + { + PropertyName = "_ImportScale", + GuiContent = Content("ImportScale") + }; + floatItem.InitTriggerByChild(); + new FeaturePopupItem(rootItem, this, "_TyFlowVATSubMode", () => Content("TyFlow VAT Sub Mode"), TyFlowVatSubModeNames, + _ => rootItem.SyncService.SyncMaterialState(), isTyflow); + new HelpBoxItem(rootItem, this, () => Text("feature.vat.tyflowUnsupportedParticle.message", "该 TyFlow VAT 类型需要 Mesh 多 UV 数据,不支持 ParticleSystem VertexStream 模式。"), MessageType.Warning, + () => isTyflow() && HasUnsupportedTyflowParticleMode(rootItem)); + new HelpBoxItem(rootItem, this, () => Text("feature.vat.tyflowUv2Conflict.message", "TyFlow VAT uses UV2 (TEXCOORD0.zw) as vertexIndex / vertexCount in ParticleSystem mode. Flipbook blending or Special UV (UV2) conflicts with it; VAT takes priority."), MessageType.Warning, + () => isTyflow() && !HasUnsupportedTyflowParticleMode(rootItem) && HasTyflowParticleUV2Conflict(rootItem)); + new ToggleItem(rootItem, this, "_DeformingSkin", () => Content("Deforming skin"), isVisible: isTyflow); + floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow) + { + PropertyName = "_SkinBoneCount", + GuiContent = Content("Skin bone count") + }; + floatItem.InitTriggerByChild(); + new ToggleItem(rootItem, this, "_RGBAEncoded", () => Content("RGBA encoded"), isVisible: isTyflow); + new ToggleItem(rootItem, this, "_RGBAHalf", () => Content("RGBA half"), isVisible: isTyflow); + new ToggleItem(rootItem, this, "_LinearToGamma", () => Content("Gamma correction"), isVisible: isTyflow); + new ToggleItem(rootItem, this, "_VATIncludesNormals", () => Content("VAT includes normals"), isVisible: isTyflow); + floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow) + { + PropertyName = "_Frame", + GuiContent = Content("Frame") + }; + floatItem.InitTriggerByChild(); + new VatFrameCustomDataItem(rootItem, this, () => Content("VAT Frame CustomData"), () => isTyflow() && hasVatFrameCustomData(), hasVatFrameCustomData); + floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow) + { + PropertyName = "_Frames", + GuiContent = Content("Frames") + }; + floatItem.InitTriggerByChild(); + new ToggleItem(rootItem, this, "_FrameInterpolation", () => Content("Frame interpolation"), isVisible: isTyflow); + new ToggleItem(rootItem, this, "_Loop", () => Content("Loop"), isVisible: isTyflow); + new ToggleItem(rootItem, this, "_InterpolateLoop", () => Content("Interpolate loop"), isVisible: isTyflow); + new ToggleItem(rootItem, this, "_Autoplay", () => Content("Autoplay"), isVisible: isTyflow); + floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow) + { + PropertyName = "_AutoplaySpeed", + GuiContent = Content("AutoplaySpeed") + }; + floatItem.InitTriggerByChild(); + InitTriggerByChild(); + } + + private static bool ShouldDrawWhenFloatOn(NBShaderRootItem rootItem, string propertyName) + { + if (!rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info)) + { + return false; + } + + return info.Property.hasMixedValue || info.Property.floatValue > 0.5f; + } + + private static bool ShouldDrawWhenFloatOff(NBShaderRootItem rootItem, string propertyName) + { + if (!rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info)) + { + return false; + } + + return info.Property.hasMixedValue || info.Property.floatValue <= 0.5f; + } + + private static bool TryGetPropertyMode(NBShaderRootItem rootItem, string propertyName, out int mode) + { + mode = 0; + if (!rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) || + info.Property.hasMixedValue) + { + return false; + } + + mode = Mathf.RoundToInt(info.Property.floatValue); + return true; + } + + private static bool ShouldDrawHoudiniRotationTexture(NBShaderRootItem rootItem) + { + return TryGetPropertyMode(rootItem, "_HoudiniVATSubMode", out int subMode) && + subMode != 3 && + ShouldDrawWhenFloatOff(rootItem, "_B_UNLOAD_ROT_TEX"); + } + + private static bool ShouldDrawCompressedNormalsToggle(NBShaderRootItem rootItem) + { + return TryGetPropertyMode(rootItem, "_HoudiniVATSubMode", out int subMode) && subMode != 3; + } + + private static bool IsVatFrameCustomDataVisible(NBShaderRootItem rootItem) + { + return IsAnyHoudiniParticleModeEnabled(rootItem) || IsAnyTyflowParticleModeEnabled(rootItem); + } + + private static bool HasTyflowParticleUV2Conflict(NBShaderRootItem rootItem) + { + if (rootItem.Mats == null || rootItem.ShaderFlags == null) + { + return false; + } + + int count = Mathf.Min(rootItem.Mats.Count, rootItem.ShaderFlags.Count); + for (int i = 0; i < count; i++) + { + Material mat = rootItem.Mats[i]; + if (!IsTyflowParticleModeEnabled(mat) || + !(rootItem.ShaderFlags[i] is NBShaderFlags flags)) + { + continue; + } + + bool flipbook = mat.IsKeywordEnabled("_FLIPBOOKBLENDING_ON"); + bool specialUVUsesUV2 = flags.CheckIsUVModeOn(NBShaderFlags.UVMode.SpecialUVChannel) && + !flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1); + if (flipbook || specialUVUsesUV2) + { + return true; + } + } + + return false; + } + + private static bool IsAnyHoudiniParticleModeEnabled(NBShaderRootItem rootItem) + { + if (rootItem.Mats == null) + { + return false; + } + + for (int i = 0; i < rootItem.Mats.Count; i++) + { + if (IsHoudiniParticleModeEnabled(rootItem.Mats[i])) + { + return true; + } + } + + return false; + } + + private static bool IsAnyTyflowParticleModeEnabled(NBShaderRootItem rootItem) + { + if (rootItem.Mats == null) + { + return false; + } + + for (int i = 0; i < rootItem.Mats.Count; i++) + { + if (IsTyflowParticleModeEnabled(rootItem.Mats[i])) + { + return true; + } + } + + return false; + } + + private static bool HasUnsupportedHoudiniParticleMode(NBShaderRootItem rootItem) + { + if (rootItem.Mats == null) + { + return false; + } + + for (int i = 0; i < rootItem.Mats.Count; i++) + { + Material mat = rootItem.Mats[i]; + if (IsHoudiniParticleModeEnabled(mat) && + GetMaterialInt(mat, "_HoudiniVATSubMode", 0) == 1) + { + return true; + } + } + + return false; + } + + private static bool HasUnsupportedTyflowParticleMode(NBShaderRootItem rootItem) + { + if (rootItem.Mats == null) + { + return false; + } + + for (int i = 0; i < rootItem.Mats.Count; i++) + { + Material mat = rootItem.Mats[i]; + if (IsVatParticleMode(mat, (int)VATMode.Tyflow) && + GetMaterialInt(mat, "_TyFlowVATSubMode", 0) >= 2) + { + return true; + } + } + + return false; + } + + private static bool IsHoudiniParticleModeEnabled(Material mat) + { + return IsVatParticleMode(mat, (int)VATMode.Houdini); + } + + private static bool IsTyflowParticleModeEnabled(Material mat) + { + return IsVatParticleMode(mat, (int)VATMode.Tyflow) && + (!mat.HasProperty("_TyFlowVATSubMode") || Mathf.RoundToInt(mat.GetFloat("_TyFlowVATSubMode")) <= 1); + } + + private static bool IsVatParticleMode(Material mat, int vatMode) + { + if (mat == null || + !mat.HasProperty("_VAT_Toggle") || + !mat.HasProperty("_VATMode") || + !mat.HasProperty("_MeshSourceMode") || + mat.GetFloat("_VAT_Toggle") <= 0.5f || + Mathf.RoundToInt(mat.GetFloat("_VATMode")) != vatMode) + { + return false; + } + + MeshSourceMode meshSourceMode = (MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode")); + return meshSourceMode == MeshSourceMode.Particle || + meshSourceMode == MeshSourceMode.UIParticle; + } + + private static int GetMaterialInt(Material mat, string propertyName, int defaultValue) + { + return mat != null && mat.HasProperty(propertyName) + ? Mathf.RoundToInt(mat.GetFloat(propertyName)) + : defaultValue; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VatFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VatFeatureItem.cs.meta new file mode 100644 index 00000000..46733468 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VatFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 744c08c430cd42fda37db42e777c3c84 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VertexOffsetFeatureItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VertexOffsetFeatureItem.cs new file mode 100644 index 00000000..d2b25c7c --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VertexOffsetFeatureItem.cs @@ -0,0 +1,62 @@ +using System; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + internal sealed class VertexOffsetFeatureItem : FeatureToggleFoldOutItem + { + public VertexOffsetFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem, "_VertexOffsetBlockFoldOut", "_VertexOffset_Toggle", "顶点偏移", keyword: "_VERTEX_OFFSET") + { + new NBShaderKeywordToggleItem( + rootItem, + this, + "_NB_Debug_VertexOffset", + "NB_DEBUG_VERTEX_OFFSET", + () => Content("顶点偏移方向测试"), + isVisible: null); + AddTextureWithWrap(rootItem, this, "_VertexOffset_Map", "顶点偏移贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP); + new UVModeSelectItem(rootItem, this, "_VertexOffsetUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP, 0, () => Content("顶点偏移贴图UV来源"), "_VertexOffset_Map"); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X, 1, () => Content("顶点扰动X轴偏移自定义曲线")); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y, 1, () => Content("顶点扰动Y轴偏移自定义曲线")); + new Vector2LineItem(rootItem, this, "_VertexOffset_Vec", true, () => Content("顶点偏移动画")); + new VectorComponentItem(rootItem, this, "_VertexOffset_Vec", 2, () => Content("顶点偏移强度"), false); + new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY, 1, () => Content("顶点扰动强度自定义曲线")); + new ToggleItem( + rootItem, + this, + "_VertexOffset_StartFromZero", + () => Content("顶点偏移从零开始"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO, enabled, 1)); + new ToggleItem( + rootItem, + this, + "_VertexOffset_NormalDir_Toggle", + () => Content("顶点偏移使用法线方向"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR, enabled)); + Func showCustomDirection = () => IsPropertyOff(rootItem, "_VertexOffset_NormalDir_Toggle"); + new VectorComponentItem(rootItem, this, "_VertexOffset_CustomDir", 0, () => Content("顶点偏移本地方向X"), false, isVisible: showCustomDirection); + new VectorComponentItem(rootItem, this, "_VertexOffset_CustomDir", 1, () => Content("顶点偏移本地方向Y"), false, isVisible: showCustomDirection); + new VectorComponentItem(rootItem, this, "_VertexOffset_CustomDir", 2, () => Content("顶点偏移本地方向Z"), false, isVisible: showCustomDirection); + + PropertyToggleBlockItem maskBlock = ToggleBlock(rootItem, "_VertexOffsetMaskBlockFoldOut", "_VertexOffset_Mask_Toggle", "顶点偏移遮罩", + parent: this, keyword: "_VERTEX_OFFSET_MASKMAP"); + AddTextureWithWrap(rootItem, maskBlock, "_VertexOffset_MaskMap", "顶点偏移遮罩图", NBShaderFlags.FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP); + new UVModeSelectItem(rootItem, maskBlock, "_VertexOffsetMaskUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP, 0, () => Content("顶点偏移遮罩图UV来源"), "_VertexOffset_MaskMap"); + new CustomDataSelectItem(rootItem, maskBlock, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X, 3, () => Content("顶点扰动遮罩X轴偏移自定义曲线")); + new CustomDataSelectItem(rootItem, maskBlock, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y, 3, () => Content("顶点扰动遮罩Y轴偏移自定义曲线")); + new Vector2LineItem(rootItem, maskBlock, "_VertexOffset_MaskMap_Vec", true, () => Content("顶点偏移遮罩动画")); + new VectorComponentItem(rootItem, maskBlock, "_VertexOffset_MaskMap_Vec", 2, () => Content("顶点偏移遮罩强度"), true); + InitTriggerByChild(); + } + + private static bool IsPropertyOff(NBShaderRootItem rootItem, string propertyName) + { + return rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) && + !info.Property.hasMixedValue && + info.Property.floatValue <= 0.5f; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VertexOffsetFeatureItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VertexOffsetFeatureItem.cs.meta new file mode 100644 index 00000000..43a33f93 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/Features/VertexOffsetFeatureItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5507463f5ee64c358b78250126100a8d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/LightBigBlockItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/LightBigBlockItem.cs new file mode 100644 index 00000000..7833919a --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/LightBigBlockItem.cs @@ -0,0 +1,358 @@ +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public enum FxLightMode + { + UnLit = 0, + BlinnPhong = 1, + HalfLambert = 2, + PBR = 3, + SixWay = 4, + UnKnownOrMixedValue = -1 + } + + public class LightBigBlockItem : BigBlockItem + { + private readonly NBShaderRootItem _nbRootItem; + private readonly FxLightModePopupItem _lightModeItem; + private readonly ToggleItem _specularToggleItem; + private readonly ColorItem _specularColorItem; + private readonly VectorComponentItem _specularSmoothnessItem; + private readonly VectorComponentItem _pbrMetallicItem; + private readonly VectorComponentItem _pbrSmoothnessItem; + private readonly PropertyToggleBlockItem _bumpBlock; + private readonly PropertyToggleBlockItem _matCapBlock; + private readonly TextureItem _sixWayPositiveItem; + private readonly TextureItem _sixWayNegativeItem; + private readonly ToggleItem _sixWayAbsorptionToggleItem; + private readonly VectorComponentItem _sixWayAbsorptionStrengthItem; + private readonly TextureItem _sixWayEmissionRampItem; + private readonly VectorComponentItem _sixWayEmissionPowItem; + private readonly ColorItem _sixWayEmissionColorItem; + + public LightBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base( + rootItem, + parentItem, + "_LightBigBlockItemFoldOut", + () => Content("block.light", "Light", "Normal, MatCap and light mode controls")) + { + _nbRootItem = rootItem; + _lightModeItem = new FxLightModePopupItem(rootItem, this); + + _specularToggleItem = new NBShaderKeywordToggleItem( + rootItem, + this, + "_BlinnPhongSpecularToggle", + "_SPECULAR_COLOR", + () => Content("light.specular.toggle", "Specular"), + isVisible: () => IsBlinnOrHalf(rootItem)); + + _specularColorItem = new ColorItem( + rootItem, + this, + "_SpecularColor", + () => Content("light.specular.color", "Specular Color"), + () => IsToggleOn(rootItem, "_BlinnPhongSpecularToggle") && IsBlinnOrHalf(rootItem)); + + _specularSmoothnessItem = new VectorComponentItem( + rootItem, + this, + "_MaterialInfo", + 1, + () => Content("light.specular.smoothness", "Smoothness"), + true, + 0f, + 1f, + () => IsToggleOn(rootItem, "_BlinnPhongSpecularToggle") && IsBlinnOrHalf(rootItem)); + + _pbrMetallicItem = new VectorComponentItem( + rootItem, + this, + "_MaterialInfo", + 0, + () => Content("light.pbr.metallic", "Metallic"), + true, + 0f, + 1f, + () => rootItem.Context.FxLightMode == FxLightMode.PBR); + + _pbrSmoothnessItem = new VectorComponentItem( + rootItem, + this, + "_MaterialInfo", + 1, + () => Content("light.pbr.smoothness", "Smoothness"), + true, + 0f, + 1f, + () => rootItem.Context.FxLightMode == FxLightMode.PBR); + + _bumpBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_BumpToggleFoldOut", + "_BumpMapToggle", + () => Content("light.bump.toggle", "Normal Map"), + keyword: "_NORMALMAP", + isVisible: () => rootItem.Context.FxLightMode != FxLightMode.SixWay); + + new TextureItem( + rootItem, + _bumpBlock, + "_BumpTex", + () => Content("light.bump.texture", "Normal Map"), + drawScaleOffset: true); + TextureRelatedFoldOutItem bumpTexRelatedFoldOut = new TextureRelatedFoldOutItem( + rootItem, + _bumpBlock, + "_BumpTexFoldOut", + "_BumpTex", + () => Content("light.bump.related", "Normal Map Related")); + new WrapModeItem(rootItem, bumpTexRelatedFoldOut, NBShaderFlags.FLAG_BIT_WRAPMODE_BUMPTEX, () => Content("light.bump.wrap", "Normal Map Wrap")); + new UVModeSelectItem( + rootItem, + bumpTexRelatedFoldOut, + "_BumpUVModeFoldOut", + NBShaderFlags.FLAG_BIT_UVMODE_POS_0_BUMPMAP, + 0, + () => Content("light.bump.uvmode", "Normal Map UV Source"), + "_BumpTex"); + new ToggleItem( + rootItem, + bumpTexRelatedFoldOut, + "_BumpMapMaskMode", + () => Content("light.bump.maskMode", "Normal Map Multi Channel"), + enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE, enabled)); + ShaderGUISliderItem bumpScaleItem = new ShaderGUISliderItem(rootItem, bumpTexRelatedFoldOut) + { + PropertyName = "_BumpScale", + GuiContent = Content("light.bump.scale", "Normal Strength"), + RangePropertyName = "BumpScaleRangeVec" + }; + bumpScaleItem.InitTriggerByChild(); + + _matCapBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_MatCapFoldOut", + "_MatCapToggle", + () => Content("light.matcap.toggle", "MatCap"), + keyword: "_MATCAP", + isVisible: () => rootItem.Context.FxLightMode != FxLightMode.SixWay); + new TextureItem(rootItem, _matCapBlock, "_MatCapTex", () => Content("light.matcap.texture", "MatCap Texture"), "_MatCapColor", false); + new VectorComponentItem(rootItem, _matCapBlock, "_MatCapInfo", 0, () => Content("light.matcap.blend", "Add/Multiply Blend"), true, 0f, 1f); + + _sixWayPositiveItem = new TextureItem( + rootItem, + this, + "_RigRTBk", + () => Content("light.sixway.positive", "SixWay Positive"), + drawScaleOffset: false, + isVisible: IsSixWay); + + _sixWayNegativeItem = new TextureItem( + rootItem, + this, + "_RigLBtF", + () => Content("light.sixway.negative", "SixWay Negative"), + drawScaleOffset: false, + isVisible: IsSixWay); + + _sixWayAbsorptionToggleItem = new NBShaderKeywordToggleItem( + rootItem, + this, + "_SixWayColorAbsorptionToggle", + "VFX_SIX_WAY_ABSORPTION", + () => Content("light.sixway.absorption.toggle", "Light Color Absorption"), + isVisible: IsSixWay); + + _sixWayAbsorptionStrengthItem = new VectorComponentItem( + rootItem, + this, + "_SixWayInfo", + 0, + () => Content("light.sixway.absorption.strength", "Absorption Strength"), + true, + 0f, + 1f, + () => IsSixWay() && IsToggleOn(rootItem, "_SixWayColorAbsorptionToggle")); + + _sixWayEmissionRampItem = new TextureItem( + rootItem, + this, + "_SixWayEmissionRamp", + () => Content("light.sixway.ramp", "SixWay Emission Ramp"), + drawScaleOffset: false, + afterDraw: SyncSixWayRampFlag, + isVisible: IsSixWay); + + _sixWayEmissionPowItem = new VectorComponentItem( + rootItem, + this, + "_SixWayInfo", + 1, + () => Content("light.sixway.emissionPow", "SixWay Emission Pow"), + false, + isVisible: IsSixWay); + + _sixWayEmissionColorItem = new ColorItem( + rootItem, + this, + "_SixWayEmissionColor", + () => Content("light.sixway.color", "SixWay Emission Color"), + IsSixWay); + + InitTriggerByChild(); + } + + public override void DrawBlock() + { + if (IsAnyLightModeAllowed()) + { + _lightModeItem.OnGUI(); + } + + if (IsTierAllowed("_SPECULAR_COLOR")) + { + _specularToggleItem.OnGUI(); + _specularColorItem.OnGUI(); + _specularSmoothnessItem.OnGUI(); + } + + if (IsTierAllowed("_FX_LIGHT_MODE_PBR")) + { + _pbrMetallicItem.OnGUI(); + _pbrSmoothnessItem.OnGUI(); + } + + if (IsTierAllowed("_NORMALMAP")) + { + _bumpBlock.OnGUI(); + } + + if (IsTierAllowed("_MATCAP")) + { + _matCapBlock.OnGUI(); + } + + if (IsTierAllowed("_FX_LIGHT_MODE_SIX_WAY")) + { + _sixWayPositiveItem.OnGUI(); + _sixWayNegativeItem.OnGUI(); + DrawSixWayWarning(); + _sixWayEmissionRampItem.OnGUI(); + _sixWayEmissionPowItem.OnGUI(); + _sixWayEmissionColorItem.OnGUI(); + } + + if (IsTierAllowed("VFX_SIX_WAY_ABSORPTION")) + { + _sixWayAbsorptionToggleItem.OnGUI(); + _sixWayAbsorptionStrengthItem.OnGUI(); + } + } + + private bool IsTierAllowed(string keyword) + { + return _nbRootItem.Context == null || _nbRootItem.Context.IsKeywordAllowed(keyword); + } + + private bool IsAnyLightModeAllowed() + { + return _nbRootItem.Context == null || + _nbRootItem.Context.IsAnyKeywordAllowed( + "_FX_LIGHT_MODE_UNLIT", + "_FX_LIGHT_MODE_BLINN_PHONG", + "_FX_LIGHT_MODE_HALF_LAMBERT", + "_FX_LIGHT_MODE_PBR", + "_FX_LIGHT_MODE_SIX_WAY"); + } + + private bool IsSixWay() + { + return _nbRootItem.Context.FxLightMode == FxLightMode.SixWay; + } + + private void DrawSixWayWarning() + { + if (!IsSixWay()) + { + return; + } + + DrawLayoutHelpBox( + NBShaderInspectorLocalization.GetInspectorText( + "light.sixway.uvWarning.message", + "六路UV跟随主贴图UV及颜色"), + MessageType.Warning); + } + + private void SyncSixWayRampFlag(MaterialProperty rampProperty) + { + if (rampProperty.hasMixedValue) + { + return; + } + + _nbRootItem.SyncService.ApplyToggleFlag( + NBShaderFlags.FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP, + rampProperty.textureValue != null, + 1); + } + + private static bool IsToggleOn(NBShaderRootItem rootItem, string propertyName) + { + return rootItem.Context.IsToggleOn(propertyName); + } + + private static bool IsBlinnOrHalf(NBShaderRootItem rootItem) + { + return rootItem.Context.FxLightMode == FxLightMode.BlinnPhong || + rootItem.Context.FxLightMode == FxLightMode.HalfLambert; + } + + private static GUIContent Content(string key, string fallback, string tip = "") + { + return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip); + } + } + + public class FxLightModePopupItem : ShaderGUIPopUpItem + { + private static readonly string[] LightModeOptions = + { + "Unlit", + "BlinnPhong", + "HalfLambert", + "PBR", + "SixWay" + }; + + private readonly NBShaderRootItem _nbRootItem; + + public FxLightModePopupItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem) + { + _nbRootItem = rootItem; + PropertyName = "_FxLightMode"; + GuiContent = NBShaderInspectorLocalization.MakeContent("inspector.light.mode.label", "Light Mode"); + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("light.mode", LightModeOptions); + InitTriggerByChild(); + } + + public override void OnGUI() + { + base.OnGUI(); + } + + public override void OnEndChange() + { + base.OnEndChange(); + _nbRootItem.SyncService.ApplyLightMode((FxLightMode)PropertyInfo.Property.floatValue); + _nbRootItem.Context.Refresh(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/LightBigBlockItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/LightBigBlockItem.cs.meta new file mode 100644 index 00000000..307733ee --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/LightBigBlockItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e6914407bf83004f8b2c13ccf777981 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/MainTexBigBlockItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/MainTexBigBlockItem.cs new file mode 100644 index 00000000..6a091357 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/MainTexBigBlockItem.cs @@ -0,0 +1,260 @@ +using UnityEditor; +using UnityEngine; +using NBShader; + +namespace NBShaderEditor +{ + public class MainTexBigBlockItem : BigBlockItem + { + private readonly NBShaderRootItem _nbRootItem; + private readonly TexturePropertyGroupItem _baseMapGroupItem; + private readonly TextureRelatedFoldOutItem _baseMapRelatedFoldOutItem; + private readonly ColorLineItem _uiColorItem; + private readonly TextureScaleOffsetItem _uiMainTexScaleOffsetItem; + private readonly ColorChannelSelectItem _alphaChannelItem; + private readonly WrapModeItem _baseMapWrapModeItem; + private readonly UVModeSelectItem _uvModeItem; + private readonly CustomDataSelectItem _offsetXCustomDataItem; + private readonly CustomDataSelectItem _offsetYCustomDataItem; + private readonly Vector2LineItem _baseMapOffsetSpeedItem; + private readonly ShaderGUISliderItem _baseMapRotationItem; + private readonly ShaderGUIFloatItem _baseMapRotationSpeedItem; + private readonly ShaderGUISliderItem _texDistortionIntensityItem; + private readonly PNoiseBlendModeItem _pNoiseBlendModeItem; + private readonly HelpBoxItem _graphicMainTexHelpBox; + + public MainTexBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base( + rootItem, + parentItem, + "_MainTexBigBlockItemFoldOut", + () => NBShaderInspectorLocalization.MakeContent( + "inspector.block.maintex.label", + "Main Texture", + "inspector.block.maintex.tip", + "Main texture and base color controls")) + { + _nbRootItem = rootItem; + _baseMapGroupItem = new TexturePropertyGroupItem( + rootItem, + this, + "_BaseMap", + "_BaseColor", + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.basemap.label", + "Main Texture"), + isVisible: () => rootItem.Context.UseGraphicMainTex == MixedBool.False, + tillingContentProvider: TillingContent, + offsetContentProvider: OffsetContent); + + _baseMapRelatedFoldOutItem = new TextureRelatedFoldOutItem( + rootItem, + this, + "_BaseMapFoldOut", + "_BaseMap", + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.basemap.related.label", + "Main Texture Related"), + () => rootItem.Context.UseGraphicMainTex == MixedBool.False); + + _graphicMainTexHelpBox = new HelpBoxItem( + rootItem, + this, + () => NBShaderInspectorLocalization.Get( + "inspector.maintex.graphic.message", + "Current mode uses Graphic texture. Only color and ST remain editable."), + MessageType.Info); + + _uiColorItem = new ColorLineItem( + rootItem, + this, + "_Color", + showLabel: false, + contentProvider: () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.uicolor.label", + "Graphic Color"), + isVisible: () => rootItem.Context.UseGraphicMainTex == MixedBool.True); + + _uiMainTexScaleOffsetItem = new TextureScaleOffsetItem( + rootItem, + this, + "_UI_MainTex_ST", + isVectorProperty: true, + isVisible: () => rootItem.Context.UseGraphicMainTex == MixedBool.True, + tillingContentProvider: TillingContent, + offsetContentProvider: OffsetContent); + + _alphaChannelItem = new ColorChannelSelectItem( + rootItem, + _baseMapRelatedFoldOutItem, + NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA, + 3, + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.alphaChannel.label", + "Alpha Channel")); + + _baseMapWrapModeItem = new WrapModeItem( + rootItem, + _baseMapRelatedFoldOutItem, + NBShaderFlags.FLAG_BIT_WRAPMODE_BASEMAP, + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.wrap.label", + "Main Texture Wrap"), + 2, + () => rootItem.Context.UseGraphicMainTex == MixedBool.False); + + _uvModeItem = new UVModeSelectItem( + rootItem, + _baseMapRelatedFoldOutItem, + "_MainTexUVModeFoldOut", + NBShaderFlags.FLAG_BIT_UVMODE_POS_0_MAINTEX, + 0, + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.uvmode.label", + "Main Texture UV Source"), + forceEnable: true, + isVisible: () => rootItem.Context.MeshSourceMode != MeshSourceMode.UIEffectSprite); + + _offsetXCustomDataItem = new CustomDataSelectItem( + rootItem, + _baseMapRelatedFoldOutItem, + NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X, + 0, + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.customdata.offsetx.label", + "Main Texture Offset X Custom Data"), + () => rootItem.Context.ParticleMode == MixedBool.True); + + _offsetYCustomDataItem = new CustomDataSelectItem( + rootItem, + _baseMapRelatedFoldOutItem, + NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y, + 0, + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.customdata.offsety.label", + "Main Texture Offset Y Custom Data"), + () => rootItem.Context.ParticleMode == MixedBool.True); + + _baseMapOffsetSpeedItem = new Vector2LineItem( + rootItem, + _baseMapRelatedFoldOutItem, + "_BaseMapMaskMapOffset", + true, + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.offsetspeed.label", + "Offset Speed"), + isVisible: () => rootItem.Context.UseGraphicMainTex == MixedBool.False); + + _baseMapRotationItem = new ShaderGUISliderItem(rootItem, _baseMapRelatedFoldOutItem) + { + PropertyName = "_BaseMapUVRotation", + GuiContent = NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.rotation.label", + "Rotation"), + Min = 0f, + Max = 360f + }; + _baseMapRotationItem.InitTriggerByChild(); + + _baseMapRotationSpeedItem = new ShaderGUIFloatItem(rootItem, _baseMapRelatedFoldOutItem) + { + PropertyName = "_BaseMapUVRotationSpeed", + GuiContent = NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.rotationspeed.label", + "Rotation Speed") + }; + _baseMapRotationSpeedItem.InitTriggerByChild(); + + _texDistortionIntensityItem = new ShaderGUISliderItem(rootItem, _baseMapRelatedFoldOutItem) + { + PropertyName = "_TexDistortion_intensity", + GuiContent = NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.distortionIntensity.label", + "Main Texture Distortion"), + RangePropertyName = "TexDistortionintensityRangeVec" + }; + _texDistortionIntensityItem.InitTriggerByChild(); + + _pNoiseBlendModeItem = new PNoiseBlendModeItem( + rootItem, + _baseMapRelatedFoldOutItem, + NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_MAINTEX, + "_MainTexPNoiseBlendOpacity", + () => NBShaderInspectorLocalization.MakeContent( + "inspector.maintex.pnoiseBlend.label", + "Main Texture Program Noise Blend"), + () => rootItem.Context.ProgramNoiseEnabled == MixedBool.True); + + InitTriggerByChild(); + } + + public override void DrawBlock() + { + if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.Mixed) + { + DrawLayoutHelpBox( + NBShaderInspectorLocalization.GetInspectorText( + "maintex.mixedMeshSource.message", + "Mixed mesh-source modes will show the matching texture controls per material state."), + MessageType.Info); + } + + _baseMapGroupItem.OnGUI(); + + if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.True) + { + _graphicMainTexHelpBox.OnGUI(); + } + + _uiColorItem.OnGUI(); + _uiMainTexScaleOffsetItem.OnGUI(); + if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.False) + { + _baseMapRelatedFoldOutItem.OnGUI(); + } + else + { + DrawMainTexRelatedItems(); + } + } + + private void DrawMainTexRelatedItems() + { + _alphaChannelItem.OnGUI(); + _baseMapWrapModeItem.OnGUI(); + _uvModeItem.OnGUI(); + _offsetXCustomDataItem.OnGUI(); + _offsetYCustomDataItem.OnGUI(); + _baseMapOffsetSpeedItem.OnGUI(); + if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.False) + { + _baseMapRotationItem.OnGUI(); + _baseMapRotationSpeedItem.OnGUI(); + } + + if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.False) + { + bool previousMixedValue = EditorGUI.showMixedValue; + EditorGUI.showMixedValue = _nbRootItem.Context.NoiseEnabled == MixedBool.Mixed; + using (new InheritedControlDisabledScope(_nbRootItem.Context.NoiseEnabled == MixedBool.False)) + { + _texDistortionIntensityItem.OnGUI(); + } + + EditorGUI.showMixedValue = previousMixedValue; + } + + _pNoiseBlendModeItem.OnGUI(); + } + + private static GUIContent TillingContent() + { + return NBShaderInspectorLocalization.MakeInspectorContent("common.tilling", "Tilling"); + } + + private static GUIContent OffsetContent() + { + return NBShaderInspectorLocalization.MakeInspectorContent("common.offset", "Offset"); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/MainTexBigBlockItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/MainTexBigBlockItem.cs.meta new file mode 100644 index 00000000..ae7749da --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/MainTexBigBlockItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ebc7f22502386443b06ac9aebc4222b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ModeBigBlockItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ModeBigBlockItem.cs new file mode 100644 index 00000000..0a16ff0c --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ModeBigBlockItem.cs @@ -0,0 +1,377 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +namespace NBShaderEditor +{ + public class ModeBigBlockItem : BigBlockItem + { + private readonly NBShaderRootItem _nbRootItem; + + public ModeBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base( + rootItem, + parentItem, + "_BigBlockModeSettingFoldOut", + () => NBShaderInspectorLocalization.MakeContent( + "inspector.block.mode.label", + "模式设置", + "inspector.block.mode.tip", + "各种基础模式设置")) + { + _nbRootItem = rootItem; + _meshModePopUp = new MeshModePopUp(rootItem, this); + _transparentMode = new TransparentModePopUp(rootItem, this); + base.InitTriggerByChild(); + } + + private MeshModePopUp _meshModePopUp; + private TransparentModePopUp _transparentMode; + + public override void DrawBlock() + { + _meshModePopUp.OnGUI(); + _transparentMode.OnGUI(); + } + } + public enum MeshSourceMode + { + Particle, + Mesh, + UIEffectRawImage, + UIEffectSprite, + UIEffectBaseMap, + UIParticle, + UnKnowOrMixed = -1 + } + + public class MeshModePopUp : ShaderGUIPopUpItem,IDisposable + { + public MeshSourceMode MeshSourceMode; + public static Dictionary MeshSourceModeDic = new Dictionary(); + public MeshModePopUp(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : + base(rootItem, parentItem: parentItem) + { + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("mode.meshSource", MeshSourceOptions); + PropertyName = "_MeshSourceMode"; + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.meshSource", "Mesh Source Mode", "Matches the current object type."); + MeshSourceModeDic[rootItem] = this; + InitTriggerByChild(); + } + + public MixedBool UIEffectEnabled() + { + if ((int)MeshSourceMode >= 2) + { + return MixedBool.True; + } + else if (MeshSourceMode == MeshSourceMode.UnKnowOrMixed) + { + return MixedBool.Mixed; + } + else + { + return MixedBool.False; + } + } + + public override void OnGUI() + { + base.OnGUI(); + if (PropertyInfo.Property.hasMixedValue) + { + MeshSourceMode = MeshSourceMode.UnKnowOrMixed; + } + else + { + MeshSourceMode = (MeshSourceMode)PropertyInfo.Property.floatValue; + } + + DrawParticleSystemMismatchWarning(); + } + + public override void OnEndChange() + { + base.OnEndChange(); + if (RootItem is NBShaderRootItem nbRootItem) + { + nbRootItem.Context.Refresh(); + } + } + + public void Dispose() + { + MeshSourceModeDic.Remove(RootItem); + } + + private void DrawParticleSystemMismatchWarning() + { + if (!(RootItem is NBShaderRootItem nbRootItem) || + nbRootItem.Mats == null || + nbRootItem.Mats.Count == 0 || + nbRootItem.Context.ParticleMode == MixedBool.True || + !nbRootItem.IsUsedByParticleSystem) + { + return; + } + + DrawLayoutHelpBox( + NBShaderInspectorLocalization.GetInspectorText( + "mode.meshSource.particleModeMismatch", + "检测到材质用在粒子系统上,和设置不匹配"), + MessageType.Error); + } + + private static readonly string[] MeshSourceOptions = + { + "粒子系统", + "模型(非粒子发射)", + "2D RawImage", + "2D 精灵", + "2D 材质贴图", + "2D UIParticle" + }; + } + + public enum TransparentMode + { + Opaque = 0, + Transparent = 1, + CutOff = 2, + UnKnowOrMixed = -1 + } + + public class TransparentModePopUp : ShaderGUIPopUpItem,IDisposable + { + + public TransparentMode TransparentMode; + public static Dictionary TransparentModeDic = + new Dictionary(); + public TransparentModePopUp(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : + base(rootItem, parentItem: parentItem) + { + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("mode.transparent", TransparentOptions); + PropertyName = "_TransparentMode"; + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.transparent", "Transparent Mode", "Controls opaque, transparent, and cutoff rendering."); + TransparentModeDic[RootItem] = this; + _cutOffSlider = new ShaderGUISliderItem(RootItem, this) + { + PropertyName = "_Cutoff", + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.cutoff", "Cutoff", "0 keeps everything, 1 clips everything.") + }; + _cutOffSlider.InitTriggerByChild(); + _blendPopUp = new BlendPopUp(RootItem, this); + PropertyInfo = RootItem.PropertyInfoDic[PropertyName]; + TransparentMode = (TransparentMode)PropertyInfo.Property.floatValue; + InitTriggerByChild(); + } + + + public override void OnGUI() + { + base.OnGUI(); + if (PropertyInfo.Property.hasMixedValue) + { + TransparentMode = TransparentMode.UnKnowOrMixed; + } + else + { + TransparentMode = (TransparentMode)PropertyInfo.Property.floatValue; + } + } + + private ShaderGUISliderItem _cutOffSlider; + private BlendPopUp _blendPopUp; + public override void DrawBlock() + { + if (TransparentMode== TransparentMode.CutOff) + { + _cutOffSlider.OnGUI(); + } + + if (TransparentMode == TransparentMode.Transparent) + { + _blendPopUp.OnGUI(); + } + + } + + public override void OnEndChange() + { + TransparentMode = (TransparentMode)PropertyInfo.Property.floatValue; + switch (TransparentMode) + { + case TransparentMode.Opaque: + if (RootItem is NBShaderRootItem opaqueRootItem) + { + opaqueRootItem.SyncService.ApplyTransparentMode(TransparentMode); + } + _blendPopUp.PropertyInfo.Property.floatValue = (float)BlendMode.Opaque; + _blendPopUp.OnEndChange(); + break; + case TransparentMode.Transparent: + if (RootItem is NBShaderRootItem transparentRootItem) + { + transparentRootItem.SyncService.ApplyTransparentMode(TransparentMode); + } + + if (_blendPopUp.BlendMode == BlendMode.Opaque) + { + _blendPopUp.PropertyInfo.Property.floatValue = (float)BlendMode.Alpha;//如果设置错误则强制设置。 + _blendPopUp.OnEndChange(); + } + + break; + case TransparentMode.CutOff: + if (RootItem is NBShaderRootItem cutOffRootItem) + { + cutOffRootItem.SyncService.ApplyTransparentMode(TransparentMode); + } + _blendPopUp.PropertyInfo.Property.floatValue = (float)BlendMode.Opaque; + _blendPopUp.OnEndChange(); + break; + } + + base.OnEndChange(); + } + + public void Dispose() + { + TransparentModeDic.Remove(RootItem);//回收时清掉相关引用。?会不会有时序问题 + } + + private static readonly string[] TransparentOptions = + { + "不透明Opaque", + "半透明Transparent", + "不透明裁剪CutOff" + }; + + + } + + public enum BlendMode + { + Alpha, // Old school alpha-blending mode, fresnel does not affect amount of transparency + Premultiply, // Physically plausible transparency mode, implemented as alpha pre-multiply + Additive, + Multiply, + Opaque, + UnKnowOrMixed = -1 + } + + public class BlendPopUp : ShaderGUIPopUpItem,IDisposable + { + public BlendMode BlendMode; + public static Dictionary BlendModeDic = new Dictionary(); + public BlendPopUp(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem) + { + PropertyName = "_Blend"; + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("mode.blend", BlendOptions); + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.blend", "Blend Mode"); + BlendModeDic[rootItem] = this; + _addToPreMultiplySlider = new AddToPreMultiplySlider(rootItem, this); + InitTriggerByChild(); + } + + public override void OnGUI() + { + base.OnGUI(); + if (PropertyInfo.Property.hasMixedValue) + { + BlendMode = BlendMode.UnKnowOrMixed; + } + else + { + BlendMode = (BlendMode)PropertyInfo.Property.floatValue; + } + } + + private AddToPreMultiplySlider _addToPreMultiplySlider; + public override void DrawBlock() + { + if (BlendMode == BlendMode.Additive || BlendMode == BlendMode.Premultiply) + { + _addToPreMultiplySlider.OnGUI(); + } + } + + public override void OnEndChange() + { + BlendMode = (BlendMode)PropertyInfo.Property.floatValue; + if (BlendMode == BlendMode.Additive) + { + _addToPreMultiplySlider.PropertyInfo.Property.floatValue = 0; + _addToPreMultiplySlider.OnEndChange(); + } + + if (BlendMode == BlendMode.Premultiply) + { + _addToPreMultiplySlider.PropertyInfo.Property.floatValue = 1; + _addToPreMultiplySlider.OnEndChange(); + } + + if (RootItem is NBShaderRootItem nbRootItem) + { + nbRootItem.SyncService.ApplyBlendMode(BlendMode); + } + + base.OnEndChange(); + } + + public void Dispose() + { + BlendModeDic.Remove(RootItem); + } + + private static readonly string[] BlendOptions = + { + "透明度混合AlphaBlend", + "预乘PreMultiply", + "叠加Additive", + "正片叠底Multiply" + }; + } + + public class AddToPreMultiplySlider : ShaderGUISliderItem + { + public AddToPreMultiplySlider(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem) + { + PropertyName = "_AdditiveToPreMultiplyAlphaLerp"; + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.additiveToPremultiply", "Additive To Premultiply", "0 is additive, 1 is premultiply."); + base.InitTriggerByChild(); + } + + public override void OnGUI() + { + base.OnGUI(); + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + float defaultValue = 0; + BlendPopUp blendPopUp = BlendPopUp.BlendModeDic[RootItem]; + if (blendPopUp.BlendMode == BlendMode.Premultiply) + { + defaultValue = 1; + } + + HasModified = !Mathf.Approximately(defaultValue,PropertyInfo.Property.floatValue); + ParentItem?.CheckIsPropertyModified(true); + + } + + public override void ExecuteReset(bool isCallByParent = false) + { + float defaultValue = 0; + BlendPopUp blendPopUp = BlendPopUp.BlendModeDic[RootItem]; + if (blendPopUp.BlendMode == BlendMode.Premultiply) + { + defaultValue = 1; + } + + PropertyInfo.Property.floatValue = defaultValue; + } + } + +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ModeBigBlockItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ModeBigBlockItem.cs.meta new file mode 100644 index 00000000..33bc0029 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ModeBigBlockItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ed09665b113c407dbfb8c818b74f48aa +timeCreated: 1758445745 \ No newline at end of file diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIContext.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIContext.cs new file mode 100644 index 00000000..0062a761 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIContext.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using NBShader; +using NBShaders2.Editor.FeatureLevel; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class NBShaderGUIContext + { + private const string FeatureTierPropertyName = "_NBShaderFeatureTier"; + + private readonly NBShaderRootItem _rootItem; + private HashSet _currentTierAllowedKeywords; + + public NBShaderGUIContext(NBShaderRootItem rootItem) + { + _rootItem = rootItem; + } + + public MeshSourceMode MeshSourceMode { get; private set; } = MeshSourceMode.UnKnowOrMixed; + public TransparentMode TransparentMode { get; private set; } = TransparentMode.UnKnowOrMixed; + public MixedBool UIEffectEnabled { get; private set; } = MixedBool.Mixed; + public MixedBool UseGraphicMainTex { get; private set; } = MixedBool.Mixed; + public MixedBool ParticleMode { get; private set; } = MixedBool.Mixed; + public MixedBool NoiseEnabled { get; private set; } = MixedBool.Mixed; + public MixedBool ProgramNoiseEnabled { get; private set; } = MixedBool.Mixed; + public MixedBool VatEnabled { get; private set; } = MixedBool.Mixed; + public MixedBool FlipbookEnabled { get; private set; } = MixedBool.Mixed; + public FxLightMode FxLightMode { get; private set; } = FxLightMode.UnKnownOrMixedValue; + public NBShaderFeatureTier CurrentTier { get; private set; } = NBShaderFeatureTier.Ultra; + public bool CurrentTierMixed { get; private set; } + + public bool IsKeywordAllowed(string keyword) + { + if (!NBShaderFeatureCatalog.IsManagedKeyword(keyword)) + { + return true; + } + + if (CurrentTierMixed) + { + return true; + } + + return _currentTierAllowedKeywords != null && _currentTierAllowedKeywords.Contains(keyword); + } + + public bool AreKeywordsAllowed(params string[] keywords) + { + if (keywords == null) + { + return true; + } + + for (int i = 0; i < keywords.Length; i++) + { + if (!IsKeywordAllowed(keywords[i])) + { + return false; + } + } + + return true; + } + + public bool IsAnyKeywordAllowed(params string[] keywords) + { + if (keywords == null || keywords.Length == 0) + { + return true; + } + + for (int i = 0; i < keywords.Length; i++) + { + if (IsKeywordAllowed(keywords[i])) + { + return true; + } + } + + return false; + } + + public bool IsAnyKeywordAllowed(string keyword0, string keyword1) + { + return IsKeywordAllowed(keyword0) || IsKeywordAllowed(keyword1); + } + + public bool IsAnyKeywordAllowed( + string keyword0, + string keyword1, + string keyword2, + string keyword3, + string keyword4) + { + return IsKeywordAllowed(keyword0) || + IsKeywordAllowed(keyword1) || + IsKeywordAllowed(keyword2) || + IsKeywordAllowed(keyword3) || + IsKeywordAllowed(keyword4); + } + + public static bool IsCatalogKeyword(string keyword) + { + return NBShaderFeatureCatalog.IsManagedKeyword(keyword); + } + + public bool HasProperty(string propertyName) + { + return _rootItem.PropertyInfoDic.ContainsKey(propertyName); + } + + public MaterialProperty GetProperty(string propertyName) + { + return _rootItem.PropertyInfoDic[propertyName].Property; + } + + public void Refresh() + { + RefreshFeatureTier(); + + if (HasProperty("_MeshSourceMode")) + { + MaterialProperty meshSourceModeProperty = GetProperty("_MeshSourceMode"); + MeshSourceMode = meshSourceModeProperty.hasMixedValue + ? MeshSourceMode.UnKnowOrMixed + : (MeshSourceMode)meshSourceModeProperty.floatValue; + } + + if (HasProperty("_TransparentMode")) + { + MaterialProperty transparentModeProperty = GetProperty("_TransparentMode"); + TransparentMode = transparentModeProperty.hasMixedValue + ? TransparentMode.UnKnowOrMixed + : (TransparentMode)transparentModeProperty.floatValue; + } + + if (MeshSourceMode == MeshSourceMode.UnKnowOrMixed) + { + UIEffectEnabled = MixedBool.Mixed; + UseGraphicMainTex = MixedBool.Mixed; + ParticleMode = MixedBool.Mixed; + } + else + { + UIEffectEnabled = (int)MeshSourceMode >= 2 ? MixedBool.True : MixedBool.False; + UseGraphicMainTex = MeshSourceMode == MeshSourceMode.UIEffectRawImage || MeshSourceMode == MeshSourceMode.UIEffectSprite + ? MixedBool.True + : MixedBool.False; + ParticleMode = MeshSourceMode == MeshSourceMode.Particle || MeshSourceMode == MeshSourceMode.UIParticle + ? MixedBool.True + : MixedBool.False; + } + + if (HasProperty("_FxLightMode")) + { + MaterialProperty lightModeProperty = GetProperty("_FxLightMode"); + FxLightMode = lightModeProperty.hasMixedValue + ? FxLightMode.UnKnownOrMixedValue + : (FxLightMode)lightModeProperty.floatValue; + } + + NoiseEnabled = IsKeywordAllowed("_NOISEMAP") ? GetToggleState("_noisemapEnabled") : MixedBool.False; + ProgramNoiseEnabled = IsKeywordAllowed("_PROGRAM_NOISE") ? GetToggleState("_ProgramNoise_Toggle") : MixedBool.False; + VatEnabled = IsKeywordAllowed("_VAT") ? GetToggleState("_VAT_Toggle") : MixedBool.False; + FlipbookEnabled = IsKeywordAllowed("_FLIPBOOKBLENDING_ON") ? GetToggleState("_FlipbookBlending") : MixedBool.False; + } + + private void RefreshFeatureTier() + { + if (!HasProperty(FeatureTierPropertyName)) + { + CurrentTier = NBShaderFeatureTier.Ultra; + CurrentTierMixed = false; + _currentTierAllowedKeywords = + NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForReadOnlyUse(CurrentTier); + return; + } + + MaterialProperty tierProperty = GetProperty(FeatureTierPropertyName); + CurrentTierMixed = tierProperty.hasMixedValue; + CurrentTier = CurrentTierMixed + ? NBShaderFeatureTier.Ultra + : ToFeatureTier(Mathf.RoundToInt(tierProperty.floatValue)); + _currentTierAllowedKeywords = CurrentTierMixed + ? null + : NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForReadOnlyUse(CurrentTier); + } + + private static NBShaderFeatureTier ToFeatureTier(int value) + { + return Enum.IsDefined(typeof(NBShaderFeatureTier), value) && value >= 0 + ? (NBShaderFeatureTier)value + : NBShaderFeatureTier.Ultra; + } + + public MixedBool GetToggleState(string propertyName) + { + if (!HasProperty(propertyName)) + { + return MixedBool.False; + } + + MaterialProperty property = GetProperty(propertyName); + if (property.hasMixedValue) + { + return MixedBool.Mixed; + } + + return property.floatValue > 0.5f ? MixedBool.True : MixedBool.False; + } + + public bool IsToggleOn(string propertyName) + { + return GetToggleState(propertyName) == MixedBool.True; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIContext.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIContext.cs.meta new file mode 100644 index 00000000..11de6083 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa789821f4c5470479fc50aac3322924 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIToolBar.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIToolBar.cs new file mode 100644 index 00000000..91030155 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIToolBar.cs @@ -0,0 +1,715 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; +using NBShader; +using NBShaders2.Editor.FeatureLevel; + +namespace NBShaderEditor +{ + public class NBShaderGUIToolBar + { + private const float ButtonWidth = 30f; + private const float TierButtonWidth = 105f; + private const string FeatureTierPropertyName = "_NBShaderFeatureTier"; + private const string HelpUrl = "https://owejt9diz2c.feishu.cn/wiki/BHz8wHHSjiYJagk7WrmcAcconlb?from=from_copylink"; + private static readonly string[] SettingsIconNames = + { + "SettingsIcon", + "d_SettingsIcon", + "Settings", + "d_Settings" + }; + + private readonly NBShaderRootItem _rootItem; + private readonly GUIContent _tierContent = new GUIContent(); + private readonly string _tierMixedLabel; + private readonly string _tierFormat; + private readonly string _tierTooltip; + private NBShaderFeatureTier _tierContentTier; + private bool _tierContentMixed; + private bool _tierContentInitialized; + private static readonly Dictionary IconContentCache = + new Dictionary(StringComparer.Ordinal); + private static readonly Dictionary TextContentCache = + new Dictionary(StringComparer.Ordinal); + private static GUIContent s_SettingsContent; + private static string s_ToolbarContentLanguage; + + private static Material copiedMaterialSnapshot; + private static Shader copiedShader; + + public NBShaderGUIToolBar(NBShaderRootItem rootItem) + { + _rootItem = rootItem; + _tierMixedLabel = Label("tierMixed", "Tier: Mixed"); + _tierFormat = Label("tierFormat", "Tier: {0}"); + _tierTooltip = Tip("tier", "NBShader feature tier"); + } + + public void DrawToolbar() + { + Rect toolbarRect = ShaderGUIItem.ApplyGlobalRectCompensation( + _rootItem.GetControlRect(EditorGUIUtility.singleLineHeight)); + GUI.Box(toolbarRect, GUIContent.none, EditorStyles.toolbar); + + Material material = MainMaterial; + bool hasMaterial = material != null; + float buttonX = toolbarRect.x; + + using (new EditorGUI.DisabledScope(!hasMaterial)) + { + if (ToolbarButton(toolbarRect, ref buttonX, IconContent("Material On Icon", "ping", "跳到当前材质"))) + { + EditorGUIUtility.PingObject(material); + } + + if (ToolbarButton(toolbarRect, ref buttonX, IconContent("TreeEditor.Trash", "cleanUnusedTextures", "清除没有使用的贴图"))) + { + CleanUnusedTextures(); + } + + if (ToolbarButton(toolbarRect, ref buttonX, TextContent("copy", "C", "复制材质属性"))) + { + CopyMaterial(material); + } + } + + using (new EditorGUI.DisabledScope(!hasMaterial || !HasCopiedMaterial())) + { + if (ToolbarButton(toolbarRect, ref buttonX, TextContent("paste", "V", "粘贴材质属性"))) + { + PasteMaterial(); + } + } + + using (new EditorGUI.DisabledScope(!hasMaterial)) + { + if (ToolbarButton(toolbarRect, ref buttonX, TextContent("specialReset", "R", "特殊重置功能"))) + { + ShowResetPopupMenu(); + } + + if (ToolbarButton(toolbarRect, ref buttonX, IconContent("d_UnityEditor.HierarchyWindow", "collapseAll", "折叠所有控件"))) + { + CollapseAll(); + } + } + + float rightX = toolbarRect.xMax; + + rightX -= ButtonWidth; + Rect helpRect = MakeToolbarButtonRect(toolbarRect, rightX); + if (GUI.Button(helpRect, IconContent("d__Help@2x", "help", "说明文档"), EditorStyles.toolbarButton)) + { + Application.OpenURL(HelpUrl); + } + + rightX -= ButtonWidth; + Rect settingsRect = MakeToolbarButtonRect(toolbarRect, rightX); + if (GUI.Button(settingsRect, SettingsContent(), EditorStyles.toolbarButton)) + { + OpenProjectSettings(); + } + + rightX -= TierButtonWidth; + Rect tierRect = MakeToolbarButtonRect(toolbarRect, rightX, TierButtonWidth); + using (new EditorGUI.DisabledScope(!hasMaterial)) + { + if (GUI.Button(tierRect, TierContent(), EditorStyles.toolbarButton)) + { + ShowTierPopupMenu(); + } + } + } + + private static bool ToolbarButton(Rect toolbarRect, ref float buttonX, GUIContent content) + { + return ToolbarButton(toolbarRect, ref buttonX, content, ButtonWidth); + } + + private static bool ToolbarButton(Rect toolbarRect, ref float buttonX, GUIContent content, float width) + { + Rect buttonRect = MakeToolbarButtonRect(toolbarRect, buttonX, width); + buttonX += width; + return GUI.Button(buttonRect, content, EditorStyles.toolbarButton); + } + + private static Rect MakeToolbarButtonRect(Rect toolbarRect, float x) + { + return MakeToolbarButtonRect(toolbarRect, x, ButtonWidth); + } + + private static Rect MakeToolbarButtonRect(Rect toolbarRect, float x, float width) + { + return new Rect(x, toolbarRect.y, width, toolbarRect.height); + } + + private static GUIContent SettingsContent() + { + EnsureToolbarContentLanguage(); + if (s_SettingsContent != null) + { + return s_SettingsContent; + } + + Texture image = null; + for (int i = 0; i < SettingsIconNames.Length; i++) + { + GUIContent icon = EditorGUIUtility.IconContent(SettingsIconNames[i]); + if (icon != null && icon.image != null) + { + image = icon.image; + break; + } + } + + s_SettingsContent = new GUIContent(image, Tip("settings", "NBShader Project Settings")); + return s_SettingsContent; + } + + private static void OpenProjectSettings() + { + SettingsService.OpenProjectSettings(NBShaderFeatureLevelSettingsProvider.SettingsPath); + } + + private static bool HasCopiedMaterial() + { + return copiedMaterialSnapshot != null; + } + + private static void CopyMaterial(Material material) + { + if (copiedMaterialSnapshot != null) + { + UnityEngine.Object.DestroyImmediate(copiedMaterialSnapshot); + copiedMaterialSnapshot = null; + copiedShader = null; + } + + if (material == null) + { + return; + } + + copiedMaterialSnapshot = new Material(material) + { + hideFlags = HideFlags.HideAndDontSave + }; + copiedShader = copiedMaterialSnapshot.shader; + } + + private GUIContent TierContent() + { + bool mixed = _rootItem.Context != null && _rootItem.Context.CurrentTierMixed; + NBShaderFeatureTier tier = CurrentTier; + if (!_tierContentInitialized || _tierContentMixed != mixed || _tierContentTier != tier) + { + _tierContent.text = mixed + ? _tierMixedLabel + : string.Format(_tierFormat, GetTierLabel(tier)); + _tierContent.tooltip = _tierTooltip; + _tierContentTier = tier; + _tierContentMixed = mixed; + _tierContentInitialized = true; + } + + return _tierContent; + } + + private NBShaderFeatureTier CurrentTier + { + get + { + return _rootItem.Context != null ? _rootItem.Context.CurrentTier : NBShaderFeatureTier.Ultra; + } + } + + private void ShowTierPopupMenu() + { + GenericMenu menu = new GenericMenu(); + AddTierMenuItem(menu, NBShaderFeatureTier.Low); + AddTierMenuItem(menu, NBShaderFeatureTier.Medium); + AddTierMenuItem(menu, NBShaderFeatureTier.High); + AddTierMenuItem(menu, NBShaderFeatureTier.Ultra); + menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); + } + + private void AddTierMenuItem(GenericMenu menu, NBShaderFeatureTier tier) + { + bool isChecked = (_rootItem.Context == null || !_rootItem.Context.CurrentTierMixed) && CurrentTier == tier; + menu.AddItem(new GUIContent(GetTierLabel(tier)), isChecked, () => SetFeatureTier(tier)); + } + + private static string GetTierLabel(NBShaderFeatureTier tier) + { + switch (tier) + { + case NBShaderFeatureTier.Low: + return Label("tierLow", "Low"); + case NBShaderFeatureTier.Medium: + return Label("tierMedium", "Medium"); + case NBShaderFeatureTier.High: + return Label("tierHigh", "High"); + case NBShaderFeatureTier.Ultra: + return Label("tierUltra", "Ultra"); + default: + return tier.ToString(); + } + } + + private void SetFeatureTier(NBShaderFeatureTier tier) + { + RecordAllMaterials(UndoText("setTier", "Set NBShader Feature Tier")); + + if (_rootItem.PropertyInfoDic.TryGetValue(FeatureTierPropertyName, out ShaderPropertyInfo info)) + { + info.Property.floatValue = (float)tier; + } + + foreach (Material mat in Materials) + { + if (mat.HasProperty(FeatureTierPropertyName)) + { + mat.SetFloat(FeatureTierPropertyName, (float)tier); + } + + NBShaderFeatureLevelMaterialApplier.Apply(mat, tier, false, true); + } + + FinishFeatureTierMutation(); + } + + private void ShowResetPopupMenu() + { + GenericMenu menu = new GenericMenu(); + menu.AddItem(new GUIContent(Label("resetAll", "重置所有")), false, ResetAll); + menu.AddItem(new GUIContent(Label("resetDisabledFeatureChildren", "重置关闭功能子属性")), false, ResetDisabledFeatureChildren); + menu.AddSeparator(string.Empty); + menu.AddItem(new GUIContent(Label("resetSpecialUV", "重置特殊UV通道")), false, ResetSpecialUVChannel); + menu.AddItem(new GUIContent(Label("resetTwirl", "重置旋转扭曲")), false, ResetTwirl); + menu.AddItem(new GUIContent(Label("resetPolar", "重置极坐标")), false, ResetPolar); + menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); + } + + private void CleanUnusedTextures() + { + RecordAllMaterials(UndoText("cleanUnusedTextures", "清除没有使用的贴图")); + foreach (Material mat in Materials) + { + CleanUnusedTextureProperties(mat); + } + + _rootItem.RequestClearUnusedTextureReferences(); + MarkAllMaterialsDirty(); + } + + private void PasteMaterial() + { + Material material = MainMaterial; + if (material == null || !HasCopiedMaterial()) + { + return; + } + + Undo.RecordObject(material, UndoText("paste", "粘贴材质属性")); + if (copiedShader != null) + { + material.shader = copiedShader; + } + + material.CopyPropertiesFromMaterial(copiedMaterialSnapshot); + + EditorUtility.SetDirty(material); + _rootItem.IsInit = true; + _rootItem.Context?.Refresh(); + _rootItem.SyncService?.SyncMaterialState(); + _rootItem.Context?.Refresh(); + UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); + GUIUtility.ExitGUI(); + } + + private void ResetSpecialUVChannel() + { + RecordAllMaterials(UndoText("resetSpecialUV", "重置特殊UV通道")); + ResetSpecialUVChannelValues(); + FinishMaterialMutation(); + } + + private void ResetTwirl() + { + RecordAllMaterials(UndoText("resetTwirl", "重置旋转扭曲")); + ResetTwirlValues(); + FinishMaterialMutation(); + } + + private void ResetPolar() + { + RecordAllMaterials(UndoText("resetPolar", "重置极坐标")); + ResetPolarValues(); + FinishMaterialMutation(); + } + + private void ResetAll() + { + RecordAllMaterials(UndoText("resetAll", "重置所有特殊功能")); + _rootItem.ExecuteResetAllItems(); + ResetSpecialUVChannelValues(); + ResetTwirlValues(); + ResetPolarValues(); + FinishMaterialMutation(); + } + + private void ResetDisabledFeatureChildren() + { + RecordAllMaterials(UndoText("resetDisabledFeatureChildren", "重置关闭功能子属性")); + foreach (ShaderGUIItem item in _rootItem.GetToolbarResetRootItems()) + { + ResetDisabledFeatureChildren(item); + } + + FinishMaterialMutation(); + } + + private static void ResetDisabledFeatureChildren(ShaderGUIItem item) + { + if (item == null) + { + return; + } + + if (item is PropertyToggleBlockItem && IsExplicitlyDisabled(item)) + { + ExecuteResetChildren(item); + item.CheckIsPropertyModified(true); + return; + } + + for (int i = 0; i < item.ChildrenItemList.Count; i++) + { + ResetDisabledFeatureChildren(item.ChildrenItemList[i]); + } + + item.CheckIsPropertyModified(true); + } + + private static bool IsExplicitlyDisabled(ShaderGUIItem item) + { + MaterialProperty property = item.PropertyInfo?.Property; + return property != null && + !property.hasMixedValue && + property.floatValue <= 0.5f; + } + + private static void ExecuteResetChildren(ShaderGUIItem item) + { + for (int i = 0; i < item.ChildrenItemList.Count; i++) + { + ExecuteResetSubtree(item.ChildrenItemList[i]); + } + } + + private static void ExecuteResetSubtree(ShaderGUIItem item) + { + if (item == null) + { + return; + } + + item.ExecuteReset(true); + for (int i = 0; i < item.ChildrenItemList.Count; i++) + { + ExecuteResetSubtree(item.ChildrenItemList[i]); + } + + item.CheckIsPropertyModified(true); + } + + private void ResetSpecialUVChannelValues() + { + float defaultValue = GetDefaultFloat("_SpecialUVChannelMode", 0f); + SetFloatProperty("_SpecialUVChannelMode", defaultValue); + + bool useTexcoord1 = Mathf.RoundToInt(defaultValue) == 0; + for (int i = 0; i < _rootItem.ShaderFlags.Count; i++) + { + ShaderFlagsBase flags = _rootItem.ShaderFlags[i]; + if (useTexcoord1) + { + flags.SetFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1, index: 1); + flags.ClearFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1); + } + else + { + flags.ClearFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1, index: 1); + flags.SetFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1); + } + } + } + + private void ResetTwirlValues() + { + float enabled = GetDefaultFloat("_UTwirlEnabled", 0f); + SetFloatProperty("_UTwirlEnabled", enabled); + SetVectorProperty("_TWParameter", GetDefaultVector("_TWParameter", new Vector4(0.5f, 0.5f, 0f, 0f))); + SetFloatProperty("_TWStrength", GetDefaultFloat("_TWStrength", 1f)); + ApplyFlag(NBShaderFlags.FLAG_BIT_PARTICLE_UTWIRL_ON, enabled > 0.5f, 0); + } + + private void ResetPolarValues() + { + float enabled = GetDefaultFloat("_PolarCoordinatesEnabled", 0f); + SetFloatProperty("_PolarCoordinatesEnabled", enabled); + SetVectorProperty("_PCCenter", GetDefaultVector("_PCCenter", new Vector4(0.5f, 0.5f, 1f, 0f))); + ApplyFlag(NBShaderFlags.FLAG_BIT_PARTICLE_POLARCOORDINATES_ON, enabled > 0.5f, 0); + } + + private void CollapseAll() + { + RecordAllMaterials(UndoText("collapseAll", "折叠所有控件")); + foreach (KeyValuePair pair in _rootItem.PropertyInfoDic) + { + if (!pair.Key.EndsWith("FoldOut", StringComparison.Ordinal)) + { + continue; + } + + MaterialProperty property = pair.Value.Property; + ShaderPropertyType propertyType = ShaderGUIUnityCompat.GetPropertyType(property); + if (propertyType == ShaderPropertyType.Float || + propertyType == ShaderPropertyType.Range) + { + property.floatValue = 0f; + } + } + + MarkAllMaterialsDirty(); + UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); + } + + private void CleanUnusedTextureProperties(Material mat) + { + if (mat == null || mat.shader == null) + { + return; + } + + Shader shader = mat.shader; + var shaderTexProps = new HashSet(); + int count = shader.GetPropertyCount(); + for (int i = 0; i < count; i++) + { + if (shader.GetPropertyType(i) == ShaderPropertyType.Texture) + { + shaderTexProps.Add(shader.GetPropertyName(i)); + } + } + + string[] texturePropertyNames = mat.GetTexturePropertyNames(); + foreach (string propertyName in texturePropertyNames) + { + if (shaderTexProps.Contains(propertyName) || mat.GetTexture(propertyName) == null) + { + continue; + } + + mat.SetTexture(propertyName, null); + Debug.LogFormat( + mat, + NBShaderInspectorLocalization.Get( + "inspector.toolbar.cleanUnusedTextures.log", + "清理 {0} 的无效贴图属性: {1}"), + mat.name, + propertyName); + } + } + + private void FinishMaterialMutation() + { + _rootItem.Context?.Refresh(); + _rootItem.SyncService?.SyncMaterialState(); + _rootItem.SyncService?.NotifyKeywordsMayHaveChanged(); + _rootItem.Context?.Refresh(); + MarkAllMaterialsDirty(); + UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); + } + + private void FinishFeatureTierMutation() + { + _rootItem.Context?.Refresh(); + _rootItem.SyncService?.NotifyKeywordsMayHaveChanged(); + _rootItem.Context?.Refresh(); + MarkAllMaterialsDirty(); + UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); + } + + private void ApplyFlag(int flagBits, bool enabled, int flagIndex) + { + for (int i = 0; i < _rootItem.ShaderFlags.Count; i++) + { + ShaderFlagsBase flags = _rootItem.ShaderFlags[i]; + if (enabled) + { + flags.SetFlagBits(flagBits, index: flagIndex); + } + else + { + flags.ClearFlagBits(flagBits, index: flagIndex); + } + } + } + + private float GetDefaultFloat(string propertyName, float fallback) + { + return _rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) + ? _rootItem.Shader.GetPropertyDefaultFloatValue(info.Index) + : fallback; + } + + private Vector4 GetDefaultVector(string propertyName, Vector4 fallback) + { + return _rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) + ? _rootItem.Shader.GetPropertyDefaultVectorValue(info.Index) + : fallback; + } + + private void SetFloatProperty(string propertyName, float value) + { + if (_rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info)) + { + info.Property.floatValue = value; + } + + foreach (Material mat in Materials) + { + if (mat.HasProperty(propertyName)) + { + mat.SetFloat(propertyName, value); + } + } + } + + private void SetVectorProperty(string propertyName, Vector4 value) + { + if (_rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info)) + { + info.Property.vectorValue = value; + } + + foreach (Material mat in Materials) + { + if (mat.HasProperty(propertyName)) + { + mat.SetVector(propertyName, value); + } + } + } + + private void RecordAllMaterials(string undoName) + { + var objects = new List(); + foreach (Material mat in Materials) + { + objects.Add(mat); + } + + if (objects.Count > 0) + { + Undo.RecordObjects(objects.ToArray(), undoName); + } + } + + private void MarkAllMaterialsDirty() + { + foreach (Material mat in Materials) + { + EditorUtility.SetDirty(mat); + } + } + + private IEnumerable Materials + { + get + { + if (_rootItem.Mats == null) + { + yield break; + } + + for (int i = 0; i < _rootItem.Mats.Count; i++) + { + Material mat = _rootItem.Mats[i]; + if (mat != null) + { + yield return mat; + } + } + } + } + + private Material MainMaterial + { + get + { + return _rootItem.Mats != null && _rootItem.Mats.Count > 0 ? _rootItem.Mats[0] : null; + } + } + + private static GUIContent IconContent(string iconName, string key, string fallbackTooltip) + { + EnsureToolbarContentLanguage(); + if (IconContentCache.TryGetValue(key, out GUIContent cachedContent)) + { + return cachedContent; + } + + GUIContent icon = EditorGUIUtility.IconContent(iconName); + var content = new GUIContent(icon != null ? icon.image : null, Tip(key, fallbackTooltip)); + IconContentCache[key] = content; + return content; + } + + private static void EnsureToolbarContentLanguage() + { + string currentLanguage = NBShaderInspectorLocalization.CurrentLanguage; + if (string.Equals(s_ToolbarContentLanguage, currentLanguage, StringComparison.Ordinal)) + { + return; + } + + s_ToolbarContentLanguage = currentLanguage; + s_SettingsContent = null; + IconContentCache.Clear(); + TextContentCache.Clear(); + } + + private static GUIContent TextContent(string key, string fallbackLabel, string fallbackTooltip) + { + EnsureToolbarContentLanguage(); + if (TextContentCache.TryGetValue(key, out GUIContent cachedContent)) + { + return cachedContent; + } + + cachedContent = NBShaderInspectorLocalization.MakeInspectorContent("toolbar." + key, fallbackLabel, fallbackTooltip); + TextContentCache[key] = cachedContent; + return cachedContent; + } + + private static string Label(string key, string fallback) + { + return NBShaderInspectorLocalization.Get("inspector.toolbar." + key + ".label", fallback); + } + + private static string Tip(string key, string fallback) + { + return NBShaderInspectorLocalization.Get("inspector.toolbar." + key + ".tip", fallback); + } + + private static string UndoText(string key, string fallback) + { + return NBShaderInspectorLocalization.Get("inspector.toolbar." + key + ".undo", fallback); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIToolBar.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIToolBar.cs.meta new file mode 100644 index 00000000..79b35c08 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderGUIToolBar.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0518e5ab9884c0e4d9b2c5ba352090ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderProtocolItems.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderProtocolItems.cs new file mode 100644 index 00000000..35fce0b6 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderProtocolItems.cs @@ -0,0 +1,1209 @@ +using System; +using UnityEditor; +using UnityEngine; +using NBShader; + +namespace NBShaderEditor +{ + public class PropertyToggleBlockItem : ShaderGUIItem + { + private readonly string _foldOutPropertyName; + private readonly Func _contentProvider; + private readonly int _flagBits; + private readonly int _flagIndex; + private readonly string _keyword; + private readonly string _shaderPassName; + private readonly Action _onValueChanged; + private readonly Func _isVisible; + private readonly GUIStyle _labelStyle; + private readonly ShaderGUIFoldOutHelper _foldOutHelper; + + public PropertyToggleBlockItem( + NBShaderRootItem rootItem, + ShaderGUIItem parentItem, + string foldOutPropertyName, + string togglePropertyName, + Func contentProvider, + int flagBits = 0, + int flagIndex = 0, + string keyword = null, + string shaderPassName = null, + Action onValueChanged = null, + Func isVisible = null, + bool bold = false) : base(rootItem, parentItem) + { + _foldOutPropertyName = foldOutPropertyName; + PropertyName = togglePropertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _flagBits = flagBits; + _flagIndex = flagIndex; + _keyword = keyword; + _shaderPassName = shaderPassName; + _onValueChanged = onValueChanged; + _isVisible = isVisible; + _labelStyle = new GUIStyle(EditorStyles.label) + { + fontStyle = bold ? FontStyle.Bold : FontStyle.Normal + }; + _foldOutHelper = new ShaderGUIFoldOutHelper(rootItem, foldOutPropertyName); + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (!FeatureToggleFoldOutItem.IsTierKeywordAllowed(RootItem as NBShaderRootItem, _keyword)) + { + return; + } + + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + MaterialProperty property = PropertyInfo.Property; + + bool enabled = property.floatValue > 0.5f; + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + bool animatedScope = BeginAnimatedPropertyBackground(ControlRect, property); + using (new EditorGUIIndentLevelScope(0)) + { + enabled = EditorGUI.Toggle(ControlRect, enabled); + } + EndAnimatedPropertyBackground(animatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + property.floatValue = enabled ? 1f : 0f; + ApplySideEffects(enabled); + OnEndChange(); + } + } + + Rect foldOutRect = LabelRect; + foldOutRect.width = Mathf.Max(0f, ControlRect.x - LabelRect.x); + _foldOutHelper.DrawFoldOut(foldOutRect); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent, _labelStyle); + } + + DrawResetButton(); + + if (_foldOutHelper.BeginFadeGroup()) + { + EditorGUI.indentLevel++; + using (new InheritedControlDisabledScope(property.hasMixedValue || property.floatValue <= 0.5f)) + { + DrawBlock(); + } + EditorGUI.indentLevel--; + } + + _foldOutHelper.EndFadedGroup(); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + base.ExecuteReset(isCallByParent); + ApplySideEffects(PropertyInfo.Property.floatValue > 0.5f); + } + + public override void DrawBlock() + { + for (int i = 0; i < ChildrenItemList.Count; i++) + { + ChildrenItemList[i].OnGUI(); + } + } + + private void ApplySideEffects(bool enabled) + { + if (RootItem is NBShaderRootItem nbRootItem) + { + if (_flagBits != 0) + { + nbRootItem.SyncService.ApplyToggleFlag(_flagBits, enabled, _flagIndex); + } + + if (!string.IsNullOrEmpty(_keyword)) + { + nbRootItem.SyncService.ApplyToggleKeyword(_keyword, enabled); + } + + if (!string.IsNullOrEmpty(_shaderPassName)) + { + nbRootItem.SyncService.ApplyShaderPass(_shaderPassName, enabled); + } + } + + _onValueChanged?.Invoke(enabled); + } + } + + public class NBShaderKeywordToggleItem : ToggleItem + { + public NBShaderKeywordToggleItem( + NBShaderRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + string keyword, + Func contentProvider, + Action onValueChanged = null, + Func isVisible = null) + : base( + rootItem, + parentItem, + propertyName, + contentProvider, + enabled => + { + rootItem.SyncService.ApplyToggleKeyword(keyword, enabled); + onValueChanged?.Invoke(enabled); + }, + FeatureToggleFoldOutItem.TierVisible(rootItem, keyword, isVisible)) + { + } + } + + public class TextureRelatedFoldOutItem : ShaderGUIItem + { + private readonly ShaderGUIFoldOutHelper _foldOutHelper; + private readonly string _texturePropertyName; + private readonly Func _contentProvider; + private readonly Func _isVisible; + + public TextureRelatedFoldOutItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string foldOutPropertyName, + string texturePropertyName, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + _foldOutHelper = new ShaderGUIFoldOutHelper(rootItem, foldOutPropertyName); + _texturePropertyName = texturePropertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + CheckIsPropertyModified(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + _foldOutHelper.DrawFoldOut(LabelRect); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent, EditorStyles.boldLabel); + } + + DrawResetButton(); + + if (_foldOutHelper.BeginFadeGroup()) + { + EditorGUI.indentLevel++; + using (new InheritedControlDisabledScope(!HasTexture())) + { + DrawBlock(); + } + + EditorGUI.indentLevel--; + } + + _foldOutHelper.EndFadedGroup(); + } + + public override void DrawBlock() + { + for (int i = 0; i < ChildrenItemList.Count; i++) + { + ChildrenItemList[i].OnGUI(); + } + } + + private bool HasTexture() + { + return RootItem.PropertyInfoDic.TryGetValue(_texturePropertyName, out ShaderPropertyInfo info) && + (info.Property.hasMixedValue || info.Property.textureValue != null); + } + } + + public class ColorChannelSelectItem : ShaderGUIItem + { + private static readonly string[] ChannelNames = { "R", "G", "B", "A" }; + private readonly Func _contentProvider; + private readonly int _colorChannelFlagPos; + private readonly int _defaultChannel; + private readonly Func _isVisible; + + public ColorChannelSelectItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + int colorChannelFlagPos, + int defaultChannel, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + _colorChannelFlagPos = colorChannelFlagPos; + _defaultChannel = Mathf.Clamp(defaultChannel, 0, 3); + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + CheckIsPropertyModified(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + int channel = GetFirstChannel(); + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = HasMixedValue(); + EditorGUI.BeginChangeCheck(); + using (new EditorGUIIndentLevelScope(0)) + { + channel = EditorGUI.Popup( + ControlRect, + channel, + NBShaderInspectorLocalization.GetInspectorOptions("protocol.colorChannel", ChannelNames)); + } + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + SetChannel(channel); + CheckIsPropertyModified(); + } + } + + DrawResetButton(); + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + PropertyIsDefaultValue = !HasMixedValue() && GetFirstChannel() == _defaultChannel; + HasModified = !PropertyIsDefaultValue; + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + SetChannel(_defaultChannel); + PropertyIsDefaultValue = true; + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + + private int GetFirstChannel() + { + NBShaderFlags flags = GetFlags(0); + return flags == null ? _defaultChannel : (int)flags.GetColorChanel(_colorChannelFlagPos); + } + + private bool HasMixedValue() + { + int first = GetFirstChannel(); + for (int i = 1; i < RootItem.ShaderFlags.Count; i++) + { + NBShaderFlags flags = GetFlags(i); + if (flags != null && (int)flags.GetColorChanel(_colorChannelFlagPos) != first) + { + return true; + } + } + + return false; + } + + private void SetChannel(int channel) + { + for (int i = 0; i < RootItem.ShaderFlags.Count; i++) + { + GetFlags(i)?.SetColorChanel((NBShaderFlags.ColorChannel)channel, _colorChannelFlagPos); + } + } + + private NBShaderFlags GetFlags(int index) + { + return index >= 0 && + index < RootItem.ShaderFlags.Count && + RootItem.ShaderFlags[index] is NBShaderFlags flags + ? flags + : null; + } + } + + public class CustomDataSelectItem : ShaderGUIItem + { + private static readonly string[] Options = + { + "关闭", + "CustomData1.x", + "CustomData1.y", + "CustomData1.z", + "CustomData1.w", + "CustomData2.x", + "CustomData2.y", + "CustomData2.z", + "CustomData2.w" + }; + + private readonly Func _contentProvider; + private readonly int _dataBitPos; + private readonly int _dataIndex; + private readonly Func _isVisible; + + public CustomDataSelectItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + int dataBitPos, + int dataIndex, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + _dataBitPos = dataBitPos; + _dataIndex = dataIndex; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + CheckIsPropertyModified(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + NBShaderFlags.CutomDataComponent component = GetFirstComponent(); + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = HasMixedValue(); + EditorGUI.BeginChangeCheck(); + int index; + using (new EditorGUIIndentLevelScope(0)) + { + index = EditorGUI.Popup( + ControlRect, + (int)component, + NBShaderInspectorLocalization.GetInspectorOptions("protocol.customData", Options)); + } + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + SetComponent((NBShaderFlags.CutomDataComponent)index); + CheckIsPropertyModified(); + if (RootItem is NBShaderRootItem nbRootItem) + { + nbRootItem.SyncService.SyncMaterialState(); + } + } + } + + DrawResetButton(); + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + PropertyIsDefaultValue = !HasMixedValue() && GetFirstComponent() == NBShaderFlags.CutomDataComponent.Off; + HasModified = !PropertyIsDefaultValue; + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + SetComponent(NBShaderFlags.CutomDataComponent.Off); + if (RootItem is NBShaderRootItem nbRootItem) + { + nbRootItem.SyncService.SyncMaterialState(); + } + + PropertyIsDefaultValue = true; + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + + private NBShaderFlags.CutomDataComponent GetFirstComponent() + { + NBShaderFlags flags = GetFlags(0); + return flags == null ? NBShaderFlags.CutomDataComponent.Off : flags.GetCustomDataFlag(_dataBitPos, _dataIndex); + } + + private bool HasMixedValue() + { + NBShaderFlags.CutomDataComponent first = GetFirstComponent(); + for (int i = 1; i < RootItem.ShaderFlags.Count; i++) + { + NBShaderFlags flags = GetFlags(i); + if (flags != null && flags.GetCustomDataFlag(_dataBitPos, _dataIndex) != first) + { + return true; + } + } + + return false; + } + + private void SetComponent(NBShaderFlags.CutomDataComponent component) + { + for (int i = 0; i < RootItem.ShaderFlags.Count; i++) + { + GetFlags(i)?.SetCustomDataFlag(component, _dataBitPos, _dataIndex); + } + } + + private NBShaderFlags GetFlags(int index) + { + return index >= 0 && + index < RootItem.ShaderFlags.Count && + RootItem.ShaderFlags[index] is NBShaderFlags flags + ? flags + : null; + } + } + + public class WrapModeItem : ShaderGUIItem + { + private static readonly string[] Options = + { + "Repeat", + "Clamp", + "RepeatX_ClampY", + "ClampX_RepeatY" + }; + + private readonly Func _contentProvider; + private readonly int _wrapFlagBits; + private readonly int _flagIndex; + private readonly Func _isVisible; + + public WrapModeItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + int wrapFlagBits, + Func contentProvider, + int flagIndex = 2, + Func isVisible = null) : base(rootItem, parentItem) + { + _wrapFlagBits = wrapFlagBits; + _flagIndex = flagIndex; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + CheckIsPropertyModified(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + int mode = GetFirstMode(); + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = HasMixedValue(); + EditorGUI.BeginChangeCheck(); + using (new EditorGUIIndentLevelScope(0)) + { + mode = EditorGUI.Popup( + ControlRect, + mode, + NBShaderInspectorLocalization.GetInspectorOptions("protocol.wrapMode", Options)); + } + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + SetMode(mode); + CheckIsPropertyModified(); + } + } + + DrawResetButton(); + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + PropertyIsDefaultValue = !HasMixedValue() && GetFirstMode() == 0; + HasModified = !PropertyIsDefaultValue; + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + SetMode(0); + PropertyIsDefaultValue = true; + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + + private int GetFirstMode() + { + ShaderFlagsBase flags = RootItem.ShaderFlags.Count > 0 ? RootItem.ShaderFlags[0] : null; + if (flags == null) + { + return 0; + } + + int mode = flags.CheckFlagBits(_wrapFlagBits, index: _flagIndex) ? 1 : 0; + if (flags.CheckFlagBits(_wrapFlagBits << 16, index: _flagIndex)) + { + mode += 2; + } + + return mode; + } + + private bool HasMixedValue() + { + int first = GetFirstMode(); + for (int i = 1; i < RootItem.ShaderFlags.Count; i++) + { + ShaderFlagsBase flags = RootItem.ShaderFlags[i]; + int mode = flags.CheckFlagBits(_wrapFlagBits, index: _flagIndex) ? 1 : 0; + if (flags.CheckFlagBits(_wrapFlagBits << 16, index: _flagIndex)) + { + mode += 2; + } + + if (mode != first) + { + return true; + } + } + + return false; + } + + private void SetMode(int mode) + { + for (int i = 0; i < RootItem.ShaderFlags.Count; i++) + { + ShaderFlagsBase flags = RootItem.ShaderFlags[i]; + SetFlag(flags, _wrapFlagBits, (mode & 1) != 0, _flagIndex); + SetFlag(flags, _wrapFlagBits << 16, (mode & 2) != 0, _flagIndex); + } + } + + private static void SetFlag(ShaderFlagsBase flags, int bits, bool enabled, int index) + { + if (enabled) + { + flags.SetFlagBits(bits, index: index); + } + else + { + flags.ClearFlagBits(bits, index: index); + } + } + } + + public class PNoiseBlendModeItem : ShaderGUIItem + { + private static readonly string[] Options = { "不使用", "Multiply", "Min", "HardLight" }; + private readonly Func _contentProvider; + private readonly int _pNoiseBlendModeFlagPos; + private readonly Func _isVisible; + private readonly ShaderGUISliderItem _opacitySlider; + + public PNoiseBlendModeItem( + NBShaderRootItem rootItem, + ShaderGUIItem parentItem, + int pNoiseBlendModeFlagPos, + string opacityPropertyName, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + _pNoiseBlendModeFlagPos = pNoiseBlendModeFlagPos; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + _opacitySlider = new ShaderGUISliderItem(rootItem, this) + { + PropertyName = opacityPropertyName, + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("protocol.pnoise.opacity", "Program Noise Blend Opacity"), + Min = 0f, + Max = 1f + }; + _opacitySlider.InitTriggerByChild(); + CheckIsPropertyModified(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + NBShaderFlags.PNoiseBlendMode mode = GetFirstMode(); + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = HasMixedValue(); + EditorGUI.BeginChangeCheck(); + int index; + using (new EditorGUIIndentLevelScope(0)) + { + index = EditorGUI.Popup( + ControlRect, + (int)mode, + NBShaderInspectorLocalization.GetInspectorOptions("protocol.pnoiseBlend", Options)); + } + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + SetMode((NBShaderFlags.PNoiseBlendMode)index); + CheckIsPropertyModified(); + } + } + + DrawResetButton(); + _opacitySlider.OnGUI(); + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + PropertyIsDefaultValue = !HasMixedValue() && GetFirstMode() == NBShaderFlags.PNoiseBlendMode.NotUse; + HasModified = !PropertyIsDefaultValue; + foreach (ShaderGUIItem childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + SetMode(NBShaderFlags.PNoiseBlendMode.NotUse); + PropertyIsDefaultValue = true; + foreach (ShaderGUIItem childItem in ChildrenItemList) + { + childItem.ExecuteReset(true); + } + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + + private NBShaderFlags.PNoiseBlendMode GetFirstMode() + { + NBShaderFlags flags = GetFlags(0); + return flags == null ? NBShaderFlags.PNoiseBlendMode.NotUse : flags.GetPNoiseBlendMode(_pNoiseBlendModeFlagPos); + } + + private bool HasMixedValue() + { + NBShaderFlags.PNoiseBlendMode first = GetFirstMode(); + for (int i = 1; i < RootItem.ShaderFlags.Count; i++) + { + NBShaderFlags flags = GetFlags(i); + if (flags != null && flags.GetPNoiseBlendMode(_pNoiseBlendModeFlagPos) != first) + { + return true; + } + } + + return false; + } + + private void SetMode(NBShaderFlags.PNoiseBlendMode mode) + { + for (int i = 0; i < RootItem.ShaderFlags.Count; i++) + { + GetFlags(i)?.SetPNoiseBlendMode(mode, _pNoiseBlendModeFlagPos); + } + } + + private NBShaderFlags GetFlags(int index) + { + return index >= 0 && + index < RootItem.ShaderFlags.Count && + RootItem.ShaderFlags[index] is NBShaderFlags flags + ? flags + : null; + } + } + + public class UVModeSelectItem : ShaderGUIItem + { + private static readonly string[] UVModeNames = + { + "默认UV通道", + "特殊UV通道", + "极坐标|旋转", + "圆柱无缝", + "主贴图", + "屏幕UV", + "世界坐标", + "局部本地坐标", + "公共UV" + }; + + private static readonly string[] PosUVModeNames = { "xy平面", "xz平面", "yz平面" }; + private static readonly string[] SpecialUVChannelNames = { "UV2_Texcoord1", "UV3_Texcoord2" }; + + private readonly Func _contentProvider; + private readonly string _foldOutPropertyName; + private readonly int _uvModeBitPos; + private readonly int _uvModeFlagIndex; + private readonly string _texturePropertyName; + private readonly bool _forceEnable; + private readonly Func _isVisible; + private readonly ShaderGUIFoldOutHelper _foldOutHelper; + + private readonly SpecialUVChannelModeItem _specialUVChannelItem; + private readonly PropertyToggleBlockItem _twirlBlock; + private readonly Vector2LineItem _twirlCenterItem; + private readonly ShaderGUIFloatItem _twirlStrengthItem; + private readonly PropertyToggleBlockItem _polarBlock; + private readonly Vector2LineItem _polarCenterItem; + private readonly VectorComponentItem _polarStrengthItem; + private readonly Vector3Item _cylinderRotateItem; + private readonly Vector3Item _cylinderOffsetItem; + private readonly ShaderGUIPopUpItem _worldSpaceItem; + private readonly ShaderGUIPopUpItem _objectSpaceItem; + + public UVModeSelectItem( + NBShaderRootItem rootItem, + ShaderGUIItem parentItem, + string foldOutPropertyName, + int uvModeBitPos, + int uvModeFlagIndex, + Func contentProvider, + string texturePropertyName = null, + bool forceEnable = false, + Func isVisible = null) : base(rootItem, parentItem) + { + _foldOutPropertyName = foldOutPropertyName; + _uvModeBitPos = uvModeBitPos; + _uvModeFlagIndex = uvModeFlagIndex; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _texturePropertyName = texturePropertyName; + _forceEnable = forceEnable; + _isVisible = isVisible; + _foldOutHelper = new ShaderGUIFoldOutHelper(rootItem, foldOutPropertyName); + GuiContent = _contentProvider(); + + _specialUVChannelItem = new SpecialUVChannelModeItem(rootItem, this); + _twirlBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_GlobalTwirlFoldOut", + "_UTwirlEnabled", + () => NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.twirl", "Twirl"), + NBShaderFlags.FLAG_BIT_PARTICLE_UTWIRL_ON, + 0); + _twirlCenterItem = new Vector2LineItem(rootItem, _twirlBlock, "_TWParameter", true, () => NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.twirlCenter", "Twirl Center")); + _twirlStrengthItem = new ShaderGUIFloatItem(rootItem, _twirlBlock) + { + PropertyName = "_TWStrength", + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.twirlStrength", "Twirl Strength") + }; + _twirlStrengthItem.InitTriggerByChild(); + + _polarBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_GlobalPolarFoldOut", + "_PolarCoordinatesEnabled", + () => NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.polar", "Polar Coordinates"), + NBShaderFlags.FLAG_BIT_PARTICLE_POLARCOORDINATES_ON, + 0); + _polarCenterItem = new Vector2LineItem(rootItem, _polarBlock, "_PCCenter", true, () => NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.polarCenter", "Polar Center")); + _polarStrengthItem = new VectorComponentItem(rootItem, _polarBlock, "_PCCenter", 2, () => NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.polarStrength", "Polar Strength"), true, 0f, 1f); + + _cylinderRotateItem = new Vector3Item(rootItem, this, "_CylinderUVRotate", () => NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.cylinderRotate", "Cylinder Rotation"), _ => UpdateCylinderMatrix(rootItem)); + _cylinderOffsetItem = new Vector3Item(rootItem, this, "_CylinderUVPosOffset", () => NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.cylinderOffset", "Cylinder Offset"), _ => UpdateCylinderMatrix(rootItem)); + + _worldSpaceItem = new ShaderGUIPopUpItem(rootItem, this) + { + PropertyName = "_WorldSpaceUVModeSelector", + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.coordinatePlane", "Coordinate Plane"), + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("protocol.uv.positionPlane", PosUVModeNames) + }; + _worldSpaceItem.InitTriggerByChild(); + + _objectSpaceItem = new ShaderGUIPopUpItem(rootItem, this) + { + PropertyName = "_ObjectSpaceUVModeSelector", + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.coordinatePlane", "Coordinate Plane"), + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("protocol.uv.positionPlane", PosUVModeNames) + }; + _objectSpaceItem.InitTriggerByChild(); + + CheckIsPropertyModified(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + bool controlDisabled = !_forceEnable && !HasTexture(); + GetRect(); + using (ParentControlDisabledScope(controlDisabled)) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + NBShaderFlags.UVMode mode = GetFirstMode(); + using (ParentControlDisabledScope(controlDisabled)) + { + EditorGUI.showMixedValue = HasMixedValue(); + EditorGUI.BeginChangeCheck(); + int index; + using (new EditorGUIIndentLevelScope(0)) + { + index = EditorGUI.Popup( + ControlRect, + (int)mode, + NBShaderInspectorLocalization.GetInspectorOptions("protocol.uv.mode", UVModeNames)); + } + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + mode = (NBShaderFlags.UVMode)index; + SetMode(mode); + _foldOutHelper.SetOpen(NeedsFoldOut(mode)); + CheckIsPropertyModified(); + } + + DrawResetButton(); + } + + bool needFoldOut = NeedsFoldOut(mode); + if (needFoldOut) + { + _foldOutHelper.DrawFoldOut(LabelRect); + } + + if (needFoldOut && !HasMixedValue()) + { + if (_foldOutHelper.BeginFadeGroup()) + { + EditorGUI.indentLevel++; + using (ParentControlDisabledScope(controlDisabled)) + { + EditorGUI.LabelField( + ApplyGlobalRectCompensation(LayoutRect()), + NBShaderInspectorLocalization.GetInspectorText( + "protocol.uv.sharedMaterial.message", + "The following settings are shared in the material:"), + EditorStyles.boldLabel); + } + using (new InheritedControlDisabledScope(controlDisabled)) + { + switch (mode) + { + case NBShaderFlags.UVMode.SpecialUVChannel: + _specialUVChannelItem.OnGUI(); + break; + case NBShaderFlags.UVMode.PolarOrTwirl: + _twirlBlock.OnGUI(); + _polarBlock.OnGUI(); + break; + case NBShaderFlags.UVMode.Cylinder: + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField( + ApplyGlobalRectCompensation(LayoutRect()), + NBShaderInspectorLocalization.GetInspectorText( + "protocol.uv.cylinderWarning.message", + "Cylinder mode is expensive. Use it carefully.")); + } + + _cylinderRotateItem.OnGUI(); + _cylinderOffsetItem.OnGUI(); + UpdateCylinderMatrix(RootItem); + break; + case NBShaderFlags.UVMode.WorldPos: + _worldSpaceItem.OnGUI(); + break; + case NBShaderFlags.UVMode.ObjectPos: + _objectSpaceItem.OnGUI(); + break; + } + } + + EditorGUI.indentLevel--; + } + + _foldOutHelper.EndFadedGroup(); + } + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + bool hasMixedValue = HasMixedValue(); + NBShaderFlags.UVMode mode = GetFirstMode(); + PropertyIsDefaultValue = !hasMixedValue && mode == NBShaderFlags.UVMode.DefaultUVChannel; + HasModified = !PropertyIsDefaultValue || (!hasMixedValue && HasActiveChildModified(mode)); + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + SetMode(NBShaderFlags.UVMode.DefaultUVChannel); + PropertyIsDefaultValue = true; + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + + private static bool NeedsFoldOut(NBShaderFlags.UVMode mode) + { + return mode != NBShaderFlags.UVMode.DefaultUVChannel && + mode != NBShaderFlags.UVMode.CommonUV && + mode != NBShaderFlags.UVMode.ScreenUV && + mode != NBShaderFlags.UVMode.MainTex; + } + + private bool HasActiveChildModified(NBShaderFlags.UVMode mode) + { + switch (mode) + { + case NBShaderFlags.UVMode.SpecialUVChannel: + return _specialUVChannelItem?.HasModified == true; + case NBShaderFlags.UVMode.PolarOrTwirl: + return _twirlBlock?.HasModified == true || _polarBlock?.HasModified == true; + case NBShaderFlags.UVMode.Cylinder: + return _cylinderRotateItem?.HasModified == true || _cylinderOffsetItem?.HasModified == true; + case NBShaderFlags.UVMode.WorldPos: + return _worldSpaceItem?.HasModified == true; + case NBShaderFlags.UVMode.ObjectPos: + return _objectSpaceItem?.HasModified == true; + default: + return false; + } + } + + private bool HasTexture() + { + if (string.IsNullOrEmpty(_texturePropertyName) || + !RootItem.PropertyInfoDic.TryGetValue(_texturePropertyName, out ShaderPropertyInfo info)) + { + return true; + } + + return info.Property.hasMixedValue || info.Property.textureValue != null; + } + + private NBShaderFlags.UVMode GetFirstMode() + { + NBShaderFlags flags = GetFlags(0); + return flags == null ? NBShaderFlags.UVMode.DefaultUVChannel : flags.GetUVMode(_uvModeBitPos, _uvModeFlagIndex); + } + + private bool HasMixedValue() + { + NBShaderFlags.UVMode first = GetFirstMode(); + for (int i = 1; i < RootItem.ShaderFlags.Count; i++) + { + NBShaderFlags flags = GetFlags(i); + if (flags != null && flags.GetUVMode(_uvModeBitPos, _uvModeFlagIndex) != first) + { + return true; + } + } + + return false; + } + + private void SetMode(NBShaderFlags.UVMode mode) + { + for (int i = 0; i < RootItem.ShaderFlags.Count; i++) + { + GetFlags(i)?.SetUVMode(mode, _uvModeBitPos, _uvModeFlagIndex); + } + } + + private NBShaderFlags GetFlags(int index) + { + return index >= 0 && + index < RootItem.ShaderFlags.Count && + RootItem.ShaderFlags[index] is NBShaderFlags flags + ? flags + : null; + } + + private static void UpdateCylinderMatrix(ShaderGUIRootItem rootItem) + { + if (!rootItem.PropertyInfoDic.TryGetValue("_CylinderUVRotate", out ShaderPropertyInfo rotateInfo) || + !rootItem.PropertyInfoDic.TryGetValue("_CylinderUVPosOffset", out ShaderPropertyInfo offsetInfo)) + { + return; + } + + Matrix4x4 cylinderMatrix = Matrix4x4.Translate(offsetInfo.Property.vectorValue) * + Matrix4x4.Rotate(Quaternion.Euler(rotateInfo.Property.vectorValue)); + SetVector(rootItem, "_CylinderMatrix0", cylinderMatrix.GetRow(0)); + SetVector(rootItem, "_CylinderMatrix1", cylinderMatrix.GetRow(1)); + SetVector(rootItem, "_CylinderMatrix2", cylinderMatrix.GetRow(2)); + SetVector(rootItem, "_CylinderMatrix3", cylinderMatrix.GetRow(3)); + } + + private static void SetVector(ShaderGUIRootItem rootItem, string propertyName, Vector4 value) + { + if (rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info)) + { + info.Property.vectorValue = value; + } + } + + private class SpecialUVChannelModeItem : ShaderGUIPopUpItem + { + public SpecialUVChannelModeItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem) + { + PropertyName = "_SpecialUVChannelMode"; + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("protocol.uv.specialChannel", "Special UV Channel"); + PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("protocol.uv.specialChannel", SpecialUVChannelNames); + InitTriggerByChild(); + } + + public override void OnGUI() + { + base.OnGUI(); + } + + public override void OnEndChange() + { + base.OnEndChange(); + bool useTexcoord1 = Mathf.RoundToInt(PropertyInfo.Property.floatValue) == 0; + for (int i = 0; i < RootItem.ShaderFlags.Count; i++) + { + ShaderFlagsBase flags = RootItem.ShaderFlags[i]; + if (useTexcoord1) + { + flags.SetFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1, index: 1); + flags.ClearFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1); + } + else + { + flags.ClearFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1, index: 1); + flags.SetFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1); + } + } + } + } + } + + public class KeywordListItem : ShaderGUIItem + { + private readonly Func _contentProvider; + private Material _cachedMaterial; + private int _cachedKeywordVersion = -1; + private string[] _cachedKeywords = Array.Empty(); + + public KeywordListItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem, Func contentProvider) : base(rootItem, parentItem) + { + _contentProvider = contentProvider ?? (() => GUIContent.none); + GuiContent = _contentProvider(); + } + + public override void OnGUI() + { + LayoutSpace(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(ApplyGlobalRectCompensation(LayoutRect()), GuiContent, EditorStyles.boldLabel); + } + + if (RootItem.Mats == null || RootItem.Mats.Count == 0 || RootItem.Mats[0] == null) + { + return; + } + + string[] keywords = GetCachedKeywords(RootItem.Mats[0]); + if (keywords == null || keywords.Length == 0) + { + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField( + ApplyGlobalRectCompensation(LayoutRect()), + NBShaderInspectorLocalization.GetInspectorText("common.none", "None")); + } + + return; + } + + for (int i = 0; i < keywords.Length; i++) + { + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(ApplyGlobalRectCompensation(LayoutRect()), keywords[i]); + } + } + } + + private string[] GetCachedKeywords(Material material) + { + int keywordVersion = RootItem is NBShaderRootItem nbRootItem && nbRootItem.SyncService != null + ? nbRootItem.SyncService.KeywordVersion + : 0; + + if (_cachedMaterial != material || _cachedKeywordVersion != keywordVersion) + { + _cachedMaterial = material; + _cachedKeywordVersion = keywordVersion; + _cachedKeywords = material != null ? material.shaderKeywords ?? Array.Empty() : Array.Empty(); + } + + return _cachedKeywords; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderProtocolItems.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderProtocolItems.cs.meta new file mode 100644 index 00000000..ee359557 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderProtocolItems.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ce0a3556e53240939194057f6b6c7976 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderSyncService.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderSyncService.cs new file mode 100644 index 00000000..b93e11f3 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderSyncService.cs @@ -0,0 +1,1069 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using NBShader; +using NBShaders2.Editor.FeatureLevel; + +namespace NBShaderEditor +{ + public class NBShaderSyncService + { + private const string FeatureTierPropertyName = "_NBShaderFeatureTier"; + private const string StencilConfigAssetPath = "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/StencilConfig.asset"; + private readonly NBShaderRootItem _rootItem; + private StencilValuesConfig _stencilValuesConfig; + + public int KeywordVersion { get; private set; } + + private static readonly FlagToggleBinding[] ToggleFlagBindings = + { + new FlagToggleBinding("_ColorAdjustmentOnlyAffectMainTex", NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX, 0), + new FlagToggleBinding("_HueShift_Toggle", NBShaderFlags.FLAG_BIT_HUESHIFT_ON, 0), + new FlagToggleBinding("_ChangeSaturability_Toggle", NBShaderFlags.FLAG_BIT_SATURABILITY_ON, 0), + new FlagToggleBinding("_Contrast_Toggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST, 1), + new FlagToggleBinding("_BaseMapColorRefine_Toggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE, 1), + new FlagToggleBinding("_ColorMultiAlpha", NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA, 0), + new FlagToggleBinding("_BaseBackColor_Toggle", NBShaderFlags.FLAG_BIT_PARTICLE_BACKCOLOR, 0), + new FlagToggleBinding("_IgnoreVetexColor_Toggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR, 1), + new FlagToggleBinding("_BumpMapMaskMode", NBShaderFlags.FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE, 0), + new FlagToggleBinding("_DistortionBothDirection_Toggle", NBShaderFlags.FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON, 0), + new FlagToggleBinding("_Distortion_Choraticaberrat_WithNoise_Toggle", NBShaderFlags.FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE, 0), + new FlagToggleBinding("_DissolveLineMaskToggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK, 1), + new FlagToggleBinding("_MaskRefineToggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_MASK_REFINE, 1), + new FlagToggleBinding("_MaskMapGradientToggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT, 1), + new FlagToggleBinding("_MaskMap2GradientToggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT, 1), + new FlagToggleBinding("_MaskMap3GradientToggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT, 1), + new FlagToggleBinding("_ScreenDistortAlphaRefineToggle", NBShaderFlags.FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE, 1), + new FlagToggleBinding("_InvertFresnel_Toggle", NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON, 0), + new FlagToggleBinding("_FresnelColorAffectByAlpha", NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA, 0), + new FlagToggleBinding("_VertexOffset_StartFromZero", NBShaderFlags.FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO, 1), + new FlagToggleBinding("_VertexOffset_NormalDir_Toggle", NBShaderFlags.FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR, 0), + new FlagToggleBinding("_UTwirlEnabled", NBShaderFlags.FLAG_BIT_PARTICLE_UTWIRL_ON, 0), + new FlagToggleBinding("_PolarCoordinatesEnabled", NBShaderFlags.FLAG_BIT_PARTICLE_POLARCOORDINATES_ON, 0) + }; + + private static readonly FlagModeBinding[] ModeFlagBindings = + { + new FlagModeBinding("_ColorBlendAlphaMultiplyMode", NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE, 0, 1), + new FlagModeBinding("_RampColorBlendMode", NBShaderFlags.FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD, 0, 1), + new FlagModeBinding("_DissolveRampColorBlendMode", NBShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY, 1, 1), + new FlagModeBinding("_FresnelMode", NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_FADE_ON, 0, 1) + }; + + private static readonly string[] HoudiniVatKeywords = + { + "_HOUDINI_VAT_SOFTBODY", + "_HOUDINI_VAT_RIGIDBODY", + "_HOUDINI_VAT_DYNAMIC_REMESH", + "_HOUDINI_VAT_PARTICLE_SPRITE" + }; + + private static readonly string[] TyflowVatKeywords = + { + "_TYFLOW_VAT_ABSOLUTE", + "_TYFLOW_VAT_RELATIVE", + "_TYFLOW_VAT_SKIN_R", + "_TYFLOW_VAT_SKIN_PR", + "_TYFLOW_VAT_SKIN_PRSAVE", + "_TYFLOW_VAT_SKIN_PRSXYZ" + }; + + public NBShaderSyncService(NBShaderRootItem rootItem) + { + _rootItem = rootItem; + } + + public static void SyncMaterialState(Material material) + { + if (material == null) + { + return; + } + + SyncMaterialState(new List { material }); + } + + public static void SyncMaterialState(IList materials) + { + if (materials == null || materials.Count == 0) + { + return; + } + + var validMaterials = new List(); + for (int i = 0; i < materials.Count; i++) + { + if (materials[i] != null) + { + validMaterials.Add(materials[i]); + } + } + + if (validMaterials.Count == 0) + { + return; + } + + var rootItem = new NBShaderRootItem + { + Mats = validMaterials, + Shader = validMaterials[0].shader + }; + rootItem.InitFlags(validMaterials); + new NBShaderSyncService(rootItem).SyncMaterialState(); + } + + public void NotifyKeywordsMayHaveChanged() + { + KeywordVersion++; + } + + public void ApplyTransparentMode(TransparentMode mode) + { + if (!_rootItem.PropertyInfoDic.ContainsKey("_ZWrite") || !_rootItem.PropertyInfoDic.ContainsKey("_QueueBias")) + { + return; + } + + MaterialProperty zWriteProperty = _rootItem.PropertyInfoDic["_ZWrite"].Property; + MaterialProperty queueBiasProperty = _rootItem.PropertyInfoDic["_QueueBias"].Property; + int queueBias = Mathf.RoundToInt(queueBiasProperty.floatValue); + + switch (mode) + { + case TransparentMode.Opaque: + zWriteProperty.floatValue = 1; + foreach (Material mat in _rootItem.Mats) + { + SetRenderQueueIfNeeded(mat, 2000 + queueBias); + SetKeyword(mat, "_ALPHATEST_ON", false); + SyncResolvedIntentStateIfNBShader(mat); + } + break; + + case TransparentMode.Transparent: + zWriteProperty.floatValue = 0; + foreach (Material mat in _rootItem.Mats) + { + SetRenderQueueIfNeeded(mat, 3000 + queueBias); + SetKeyword(mat, "_ALPHATEST_ON", false); + SyncResolvedIntentStateIfNBShader(mat); + } + break; + + case TransparentMode.CutOff: + zWriteProperty.floatValue = 1; + foreach (Material mat in _rootItem.Mats) + { + SetRenderQueueIfNeeded(mat, 2450 + queueBias); + SetKeyword(mat, "_ALPHATEST_ON", true); + SyncResolvedIntentStateIfNBShader(mat); + } + break; + } + } + + public void SyncMaterialState() + { + for (int i = 0; i < _rootItem.Mats.Count; i++) + { + Material mat = _rootItem.Mats[i]; + if (mat == null) + { + continue; + } + + NBShaderFlags flags = GetFlags(i); + SyncMeshSourceMode(mat, flags); + SyncCustomData(mat, flags); + SyncUVDerivedFlags(flags); + SyncTransparentMode(mat); + SyncTransparentShadowFlags(mat, flags); + SyncBlendMode(mat); + SyncTimeMode(mat, flags); + SyncTogglePropertyFlags(mat, flags); + SyncParallaxLayerCount(mat); + SyncResolvedIntentState(mat); + } + } + + public void ApplyToggleFlag(int flagBits, bool enabled, int flagIndex = 0) + { + foreach (ShaderFlagsBase flagBase in _rootItem.ShaderFlags) + { + if (enabled) + { + SetFlag(flagBase, flagBits, true, flagIndex); + } + else + { + SetFlag(flagBase, flagBits, false, flagIndex); + } + } + } + + public void ApplyShaderPass(string passName, bool enabled) + { + foreach (Material mat in _rootItem.Mats) + { + if (IsResolvedIntentPass(passName) && NBShaderMaterialIntentResolver.IsNBShaderMaterial(mat)) + SyncResolvedIntentState(mat); + else + SetShaderPassEnabledIfNeeded(mat, passName, enabled); + } + } + + public void ApplyScreenDistortMode(int mode) + { + foreach (Material mat in _rootItem.Mats) + { + if (mat == null) + continue; + + if (mode == 0 && mat.HasProperty("_DisableMainPassToggle")) + { + SetFloatIfExists(mat, "_DisableMainPassToggle", 0f); + } + + if (NBShaderMaterialIntentResolver.IsNBShaderMaterial(mat)) + SyncResolvedIntentState(mat); + } + } + + public void ApplyDepthDecalEnabled(bool enabled) + { + ApplyToggleKeyword("_DEPTH_DECAL", enabled); + foreach (Material mat in _rootItem.Mats) + { + if (mat == null) + { + continue; + } + + ApplyStencilPresetToMaterial(mat, enabled ? "ParticleBaseDecal" : "ParticleBaseDefault"); + SetFloatIfExists(mat, "_CustomStencilTest", enabled ? 1f : 0f); + SetFloatIfExists(mat, "_Cull", enabled ? (float)RenderFace.Back : (float)RenderFace.Front); + SetFloatIfExists(mat, "_ZTest", enabled + ? (float)UnityEngine.Rendering.CompareFunction.GreaterEqual + : (float)UnityEngine.Rendering.CompareFunction.LessEqual); + } + } + + public void ApplyPortalState() + { + foreach (Material mat in _rootItem.Mats) + { + if (mat == null) + { + continue; + } + + bool portal = mat.HasProperty("_Portal_Toggle") && mat.GetFloat("_Portal_Toggle") > 0.5f; + bool mask = mat.HasProperty("_Portal_MaskToggle") && mat.GetFloat("_Portal_MaskToggle") > 0.5f; + if (!portal) + { + ApplyStencilPresetToMaterial(mat, "ParticleBaseDefault"); + SetFloatIfExists(mat, "_CustomStencilTest", 0f); + SetFloatIfExists(mat, "_TransparentMode", (float)TransparentMode.Transparent); + SetFloatIfExists(mat, "_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); + SetFloatIfExists(mat, "_ForceZWriteToggle", 0f); + } + else if (mask) + { + ApplyStencilPresetToMaterial(mat, "ParticalBasePortalMask"); + SetFloatIfExists(mat, "_CustomStencilTest", 1f); + if (mat.HasProperty("_TransparentMode") && + Mathf.RoundToInt(mat.GetFloat("_TransparentMode")) == (int)TransparentMode.Transparent) + { + SetFloatIfExists(mat, "_TransparentMode", (float)TransparentMode.CutOff); + } + + SetFloatIfExists(mat, "_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); + SetFloatIfExists(mat, "_ForceZWriteToggle", 2f); + } + else + { + ApplyStencilPresetToMaterial(mat, "ParticalBasePortal"); + SetFloatIfExists(mat, "_CustomStencilTest", 1f); + } + } + + SyncMaterialState(); + } + + public void ApplyVatEnabled(bool enabled) + { + foreach (Material mat in _rootItem.Mats) + { + SetFloatIfExists(mat, "_VAT_Toggle", enabled ? 1f : 0f); + + if (enabled) + DisableFlipbook(mat); + + if (NBShaderMaterialIntentResolver.IsNBShaderMaterial(mat)) + SyncResolvedIntentState(mat); + else + SyncVatKeywords(mat); + } + } + + public void ApplyFlipbookEnabled(bool enabled) + { + foreach (Material mat in _rootItem.Mats) + { + SetFloatIfExists(mat, "_FlipbookBlending", enabled ? 1f : 0f); + + if (enabled) + { + DisableVat(mat); + } + + if (NBShaderMaterialIntentResolver.IsNBShaderMaterial(mat)) + SyncResolvedIntentState(mat); + else + SetKeyword(mat, "_FLIPBOOKBLENDING_ON", enabled); + } + } + + public void ApplyBlendMode(BlendMode mode) + { + foreach (Material mat in _rootItem.Mats) + { + bool nbShaderMaterial = NBShaderMaterialIntentResolver.IsNBShaderMaterial(mat); + switch (mode) + { + case BlendMode.Alpha: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + if (!nbShaderMaterial) + { + SetKeyword(mat, "_ALPHAPREMULTIPLY_ON", false); + SetKeyword(mat, "_ALPHAMODULATE_ON", false); + } + break; + case BlendMode.Premultiply: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + if (!nbShaderMaterial) + { + SetKeyword(mat, "_ALPHAPREMULTIPLY_ON", true); + SetKeyword(mat, "_ALPHAMODULATE_ON", false); + } + break; + case BlendMode.Additive: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + if (!nbShaderMaterial) + { + SetKeyword(mat, "_ALPHAPREMULTIPLY_ON", true); + SetKeyword(mat, "_ALPHAMODULATE_ON", false); + } + break; + case BlendMode.Multiply: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + if (!nbShaderMaterial) + { + SetKeyword(mat, "_ALPHAPREMULTIPLY_ON", false); + SetKeyword(mat, "_ALPHAMODULATE_ON", true); + } + break; + case BlendMode.Opaque: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + if (!nbShaderMaterial) + { + SetKeyword(mat, "_ALPHAPREMULTIPLY_ON", false); + SetKeyword(mat, "_ALPHAMODULATE_ON", false); + } + break; + } + + if (nbShaderMaterial) + SyncResolvedIntentState(mat); + } + } + + public void ApplyLightMode(FxLightMode mode) + { + foreach (Material mat in _rootItem.Mats) + { + if (NBShaderMaterialIntentResolver.IsNBShaderMaterial(mat)) + SyncResolvedIntentState(mat); + else + SetLightModeKeyword(mat, mode); + } + } + + public void ApplyToggleKeyword(string keyword, bool enabled) + { + foreach (Material mat in _rootItem.Mats) + { + if (NBShaderFeatureCatalog.IsManagedKeyword(keyword) && + NBShaderMaterialIntentResolver.IsNBShaderMaterial(mat)) + SyncResolvedIntentState(mat); + else + SetKeyword(mat, keyword, enabled); + } + } + + public void ApplyStencilPreset(string key) + { + foreach (Material mat in _rootItem.Mats) + { + if (mat == null) + { + continue; + } + + ApplyStencilPresetToMaterial(mat, key); + } + } + + public bool AnyProgramNoiseEnabled() + { + foreach (Material mat in _rootItem.Mats) + { + if (mat.HasProperty("_ProgramNoise_Toggle") && mat.GetFloat("_ProgramNoise_Toggle") > 0.5f) + { + return true; + } + } + + return false; + } + + private NBShaderFlags GetFlags(int index) + { + return index >= 0 && + index < _rootItem.ShaderFlags.Count && + _rootItem.ShaderFlags[index] is NBShaderFlags flags + ? flags + : null; + } + + private StencilValuesConfig GetStencilValuesConfig() + { + if (_stencilValuesConfig == null) + { + _stencilValuesConfig = AssetDatabase.LoadAssetAtPath(StencilConfigAssetPath); + } + + return _stencilValuesConfig; + } + + private void ApplyStencilPresetToMaterial(Material mat, string key) + { + StencilValuesConfig config = GetStencilValuesConfig(); + if (config != null) + { + StencilTestHelper.SetMaterialStencil(mat, key, config, out _); + } + else + { + ApplyFallbackStencilPreset(mat, key); + } + } + + private static void ApplyFallbackStencilPreset(Material mat, string key) + { + int stencil = 0; + int comp = (int)UnityEngine.Rendering.CompareFunction.Always; + int pass = (int)UnityEngine.Rendering.StencilOp.Keep; + int keyIndex = 0; + + switch (key) + { + case "ParticalBasePortal": + stencil = 200; + comp = (int)UnityEngine.Rendering.CompareFunction.Equal; + keyIndex = 2; + break; + case "ParticalBasePortalMask": + stencil = 200; + pass = (int)UnityEngine.Rendering.StencilOp.Replace; + keyIndex = 3; + break; + case "ParticleBaseDecal": + stencil = 2; + comp = (int)UnityEngine.Rendering.CompareFunction.GreaterEqual; + keyIndex = 4; + break; + case "ParticleWithoutPlayer": + stencil = 5; + comp = (int)UnityEngine.Rendering.CompareFunction.Greater; + keyIndex = 5; + break; + } + + SetFloatIfExists(mat, "_Stencil", stencil); + SetFloatIfExists(mat, "_StencilComp", comp); + SetFloatIfExists(mat, "_StencilOp", pass); + SetFloatIfExists(mat, "_StencilFail", (int)UnityEngine.Rendering.StencilOp.Keep); + SetFloatIfExists(mat, "_StencilZFail", (int)UnityEngine.Rendering.StencilOp.Keep); + SetFloatIfExists(mat, "_StencilReadMask", 255f); + SetFloatIfExists(mat, "_StencilWriteMask", 255f); + SetFloatIfExists(mat, "_StencilKeyIndex", keyIndex); + } + + private static void SetFloatIfExists(Material mat, string propertyName, float value) + { + if (mat != null && + mat.HasProperty(propertyName) && + !Mathf.Approximately(mat.GetFloat(propertyName), value)) + { + mat.SetFloat(propertyName, value); + } + } + + private static void SetIntIfExists(Material mat, string propertyName, int value) + { + if (mat != null && + mat.HasProperty(propertyName) && + Mathf.RoundToInt(mat.GetFloat(propertyName)) != value) + { + mat.SetInt(propertyName, value); + } + } + + private static void SetVectorIfExists(Material mat, string propertyName, Vector4 value) + { + if (mat != null && + mat.HasProperty(propertyName) && + mat.GetVector(propertyName) != value) + { + mat.SetVector(propertyName, value); + } + } + + private static void SetRenderQueueIfNeeded(Material mat, int renderQueue) + { + if (mat != null && mat.renderQueue != renderQueue) + { + mat.renderQueue = renderQueue; + } + } + + private static void SetShaderPassEnabledIfNeeded(Material mat, string passName, bool enabled) + { + if (mat != null && !string.IsNullOrEmpty(passName) && mat.GetShaderPassEnabled(passName) != enabled) + { + mat.SetShaderPassEnabled(passName, enabled); + } + } + + private void SyncMeshSourceMode(Material mat, NBShaderFlags flags) + { + if (flags == null || !mat.HasProperty("_MeshSourceMode")) + { + return; + } + + MeshSourceMode mode = (MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode")); + bool isParticle = mode == MeshSourceMode.Particle || mode == MeshSourceMode.UIParticle; + bool isUIEffect = mode == MeshSourceMode.UIEffectRawImage || + mode == MeshSourceMode.UIEffectSprite || + mode == MeshSourceMode.UIEffectBaseMap || + mode == MeshSourceMode.UIParticle; + bool useBaseMapTexture = mode == MeshSourceMode.UIEffectBaseMap || + mode == MeshSourceMode.UIParticle; + + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM, isParticle, 1); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_UV_FROM_MESH, mode == MeshSourceMode.Mesh, 1); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_UIEFFECT_ON, isUIEffect, 0); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE, mode == MeshSourceMode.UIEffectSprite, 1); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE, useBaseMapTexture, 1); + if (mode == MeshSourceMode.Particle) + { + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER, false, 1); + } + + if (mat.HasProperty("_CustomData")) + { + SetFloatIfExists(mat, "_CustomData", isParticle ? 1f : 0f); + } + + if (isParticle) + { + SetKeyword(mat, "_CUSTOMDATA", true); + } + else + { + SetKeyword(mat, "_CUSTOMDATA", false); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA1_ON, false, 0); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA2_ON, false, 0); + } + } + + private void SyncTimeMode(Material mat, NBShaderFlags flags) + { + if (flags == null || !mat.HasProperty("_TimeMode")) + { + return; + } + + TimeMode mode = (TimeMode)Mathf.RoundToInt(mat.GetFloat("_TimeMode")); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_UNSCALETIME_ON, mode == TimeMode.UnScaleTime, 0); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON, mode == TimeMode.ScriptableTime, 0); + } + + private void SyncTogglePropertyFlags(Material mat, NBShaderFlags flags) + { + if (flags == null || mat == null) + { + return; + } + + for (int i = 0; i < ToggleFlagBindings.Length; i++) + { + var binding = ToggleFlagBindings[i]; + if (!mat.HasProperty(binding.propertyName)) + { + continue; + } + + SetFlag(flags, binding.flagBits, mat.GetFloat(binding.propertyName) > 0.5f, binding.flagIndex); + } + + for (int i = 0; i < ModeFlagBindings.Length; i++) + { + var binding = ModeFlagBindings[i]; + if (!mat.HasProperty(binding.propertyName)) + { + continue; + } + + SetFlag(flags, binding.flagBits, Mathf.RoundToInt(mat.GetFloat(binding.propertyName)) == binding.enabledMode, binding.flagIndex); + } + } + + private bool IsKeywordAllowed(string keyword) + { + return _rootItem.Context == null || _rootItem.Context.IsKeywordAllowed(keyword); + } + + private void SetKeyword(Material mat, string keyword, bool enabled) + { + if (mat == null || string.IsNullOrEmpty(keyword)) + { + return; + } + + bool shouldEnable = enabled && IsKeywordAllowed(keyword); + if (mat.IsKeywordEnabled(keyword) == shouldEnable) + { + return; + } + + if (shouldEnable) + { + mat.EnableKeyword(keyword); + } + else + { + mat.DisableKeyword(keyword); + } + + KeywordVersion++; + } + + private void SyncResolvedIntentState(Material mat) + { + var tier = ResolveMaterialTier(mat); + var allowedKeywords = NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForReadOnlyUse(tier); + var allowedPassFeatures = NBShaderFeatureLevelProjectSettings.instance.GetAllowedPassFeatureSetForReadOnlyUse(tier); + var result = NBShaderMaterialIntentResolver.Resolve(mat, tier, allowedKeywords, allowedPassFeatures); + var effectiveKeywords = new HashSet(result.effectiveKeywords); + + for (int i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++) + { + string keyword = NBShaderFeatureCatalog.RawKeywords[i]; + SetKeyword(mat, keyword, effectiveKeywords.Contains(keyword)); + } + + for (int i = 0; i < result.passes.Length; i++) + { + NBShaderPassIntent pass = result.passes[i]; + if (!string.IsNullOrEmpty(pass.passName)) + { + SetShaderPassEnabledIfNeeded(mat, pass.passName, pass.included); + } + } + + SetKeyword(mat, "EVALUATE_SH_VERTEX", effectiveKeywords.Contains("_FX_LIGHT_MODE_SIX_WAY")); + } + + private void SyncResolvedIntentStateIfNBShader(Material mat) + { + if (NBShaderMaterialIntentResolver.IsNBShaderMaterial(mat)) + SyncResolvedIntentState(mat); + } + + private NBShaderFeatureTier ResolveMaterialTier(Material mat) + { + if (mat != null && mat.HasProperty(FeatureTierPropertyName)) + { + int value = Mathf.RoundToInt(mat.GetFloat(FeatureTierPropertyName)); + if (value >= (int)NBShaderFeatureTier.Low && value <= (int)NBShaderFeatureTier.Ultra) + { + return (NBShaderFeatureTier)value; + } + } + + if (_rootItem.Context != null && !_rootItem.Context.CurrentTierMixed) + { + return _rootItem.Context.CurrentTier; + } + + return NBShaderFeatureTier.Ultra; + } + + private static bool IsResolvedIntentPass(string passName) + { + if (string.IsNullOrEmpty(passName)) + return false; + + if (string.Equals(passName, NBShaderPassFeatureCatalog.MainForwardPassName, StringComparison.Ordinal)) + return true; + + string passFeatureId; + return NBShaderFeatureLevelCatalog.TryGetManagedPassFeatureByPassName(passName, out passFeatureId); + } + + private void SyncCustomData(Material mat, NBShaderFlags flags) + { + if (flags == null || !mat.HasProperty("_MeshSourceMode")) + { + return; + } + + MeshSourceMode mode = (MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode")); + bool isParticle = mode == MeshSourceMode.Particle || mode == MeshSourceMode.UIParticle; + if (!isParticle) + { + return; + } + + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA1_ON, flags.IsCustomData1On(), 0); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA2_ON, flags.IsCustomData2On(), 0); + } + + private static void SyncUVDerivedFlags(NBShaderFlags flags) + { + if (flags == null) + { + return; + } + + if (!flags.CheckIsUVModeOn(NBShaderFlags.UVMode.SpecialUVChannel)) + { + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1, false, 1); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, false, 1); + } + + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE, flags.CheckIsUVModeOn(NBShaderFlags.UVMode.Cylinder), 1); + } + + private void SyncTransparentMode(Material mat) + { + if (!mat.HasProperty("_TransparentMode")) + { + return; + } + + TransparentMode mode = (TransparentMode)Mathf.RoundToInt(mat.GetFloat("_TransparentMode")); + int queueBias = mat.HasProperty("_QueueBias") ? Mathf.RoundToInt(mat.GetFloat("_QueueBias")) : 0; + bool uiEffect = mat.HasProperty("_MeshSourceMode") && + ((MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode")) == MeshSourceMode.UIEffectRawImage || + (MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode")) == MeshSourceMode.UIEffectSprite || + (MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode")) == MeshSourceMode.UIEffectBaseMap || + (MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode")) == MeshSourceMode.UIParticle); + + if (mode != TransparentMode.Transparent) + { + SetFloatIfExists(mat, "_TransparentShadowDitherToggle", 0f); + } + + switch (mode) + { + case TransparentMode.Opaque: + SetIntIfExists(mat, "_ZWrite", 1); + SetRenderQueueIfNeeded(mat, 2100 + queueBias); + SetFloatIfExists(mat, "_Blend", (float)BlendMode.Opaque); + break; + case TransparentMode.Transparent: + SetIntIfExists(mat, "_ZWrite", 0); + SetRenderQueueIfNeeded(mat, (uiEffect ? 3000 : 3100) + queueBias); + if (mat.HasProperty("_Blend") && (BlendMode)Mathf.RoundToInt(mat.GetFloat("_Blend")) == BlendMode.Opaque) + { + SetFloatIfExists(mat, "_Blend", (float)BlendMode.Alpha); + } + + break; + case TransparentMode.CutOff: + SetIntIfExists(mat, "_ZWrite", 1); + SetRenderQueueIfNeeded(mat, 2450 + queueBias); + SetFloatIfExists(mat, "_Blend", (float)BlendMode.Opaque); + break; + } + + if (mat.HasProperty("_ForceZWriteToggle")) + { + float forceZWrite = mat.GetFloat("_ForceZWriteToggle"); + if (forceZWrite > 0.5f && forceZWrite < 1.5f) + { + SetIntIfExists(mat, "_ZWrite", 1); + } + else if (forceZWrite > 1.5f) + { + SetIntIfExists(mat, "_ZWrite", 0); + } + } + } + + private static void SyncTransparentShadowFlags(Material mat, NBShaderFlags flags) + { + TransparentMode mode = mat != null && mat.HasProperty("_TransparentMode") + ? (TransparentMode)Mathf.RoundToInt(mat.GetFloat("_TransparentMode")) + : TransparentMode.UnKnowOrMixed; + bool isTransparent = mode == TransparentMode.Transparent; + bool useTransparentShadowDither = isTransparent && + mat.HasProperty("_TransparentShadowDitherToggle") && + mat.GetFloat("_TransparentShadowDitherToggle") > 0.5f; + + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_TRANSPARENT_MODE, isTransparent, 1); + SetFlag(flags, NBShaderFlags.FLAG_BIT_PARTICLE_1_TRANSPARENT_SHADOW_DITHER, useTransparentShadowDither, 1); + } + + private static bool IsUIEffectMode(Material mat) + { + if (mat == null || !mat.HasProperty("_MeshSourceMode")) + { + return false; + } + + MeshSourceMode meshSourceMode = (MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode")); + return meshSourceMode == MeshSourceMode.UIEffectRawImage || + meshSourceMode == MeshSourceMode.UIEffectSprite || + meshSourceMode == MeshSourceMode.UIEffectBaseMap || + meshSourceMode == MeshSourceMode.UIParticle; + } + + private static void SyncParallaxLayerCount(Material mat) + { + if (mat == null || + !mat.HasProperty("_ParallaxMapping_Toggle") || + !mat.HasProperty("_ParallaxMapping_Vec") || + mat.GetFloat("_ParallaxMapping_Toggle") <= 0.5f) + { + return; + } + + Vector4 value = mat.GetVector("_ParallaxMapping_Vec"); + if (value.y < value.x + 1f) + { + value.y = value.x + 1f; + SetVectorIfExists(mat, "_ParallaxMapping_Vec", value); + } + } + + private void SyncBlendMode(Material mat) + { + if (!mat.HasProperty("_Blend")) + { + return; + } + + switch ((BlendMode)Mathf.RoundToInt(mat.GetFloat("_Blend"))) + { + case BlendMode.Alpha: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + break; + case BlendMode.Premultiply: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + break; + case BlendMode.Additive: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + break; + case BlendMode.Multiply: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + break; + case BlendMode.Opaque: + SetIntIfExists(mat, "_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + SetIntIfExists(mat, "_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + break; + } + } + + private void SetLightModeKeyword(Material mat, FxLightMode mode) + { + SetKeyword(mat, "_FX_LIGHT_MODE_UNLIT", false); + SetKeyword(mat, "_FX_LIGHT_MODE_BLINN_PHONG", false); + SetKeyword(mat, "_FX_LIGHT_MODE_HALF_LAMBERT", false); + SetKeyword(mat, "_FX_LIGHT_MODE_PBR", false); + SetKeyword(mat, "_FX_LIGHT_MODE_SIX_WAY", false); + SetKeyword(mat, "EVALUATE_SH_VERTEX", false); + + switch (mode) + { + case FxLightMode.UnLit: + SetKeyword(mat, "_FX_LIGHT_MODE_UNLIT", true); + break; + case FxLightMode.BlinnPhong: + SetKeyword(mat, "_FX_LIGHT_MODE_BLINN_PHONG", true); + break; + case FxLightMode.HalfLambert: + SetKeyword(mat, "_FX_LIGHT_MODE_HALF_LAMBERT", true); + break; + case FxLightMode.PBR: + SetKeyword(mat, "_FX_LIGHT_MODE_PBR", true); + break; + case FxLightMode.SixWay: + SetKeyword(mat, "_FX_LIGHT_MODE_SIX_WAY", true); + SetKeyword(mat, "EVALUATE_SH_VERTEX", true); + break; + } + } + + private void SyncVatKeywords(Material mat) + { + if (!mat.HasProperty("_VAT_Toggle") || mat.GetFloat("_VAT_Toggle") <= 0.5f) + { + ClearVatKeywords(mat); + return; + } + + DisableFlipbook(mat); + SetKeyword(mat, "_VAT", true); + int vatMode = mat.HasProperty("_VATMode") ? Mathf.RoundToInt(mat.GetFloat("_VATMode")) : 0; + if (vatMode == (int)VATMode.Tyflow) + { + SetKeyword(mat, "_VAT_HOUDINI", false); + SetKeyword(mat, "_VAT_TYFLOW", true); + SetHoudiniVATKeyword(mat, -1); + SetTyflowVATKeyword(mat, mat.HasProperty("_TyFlowVATSubMode") ? Mathf.RoundToInt(mat.GetFloat("_TyFlowVATSubMode")) : 0); + } + else + { + SetKeyword(mat, "_VAT_HOUDINI", true); + SetKeyword(mat, "_VAT_TYFLOW", false); + SetHoudiniVATKeyword(mat, mat.HasProperty("_HoudiniVATSubMode") ? Mathf.RoundToInt(mat.GetFloat("_HoudiniVATSubMode")) : 0); + SetTyflowVATKeyword(mat, -1); + } + } + + private void DisableVat(Material mat) + { + SetFloatIfExists(mat, "_VAT_Toggle", 0f); + + ClearVatKeywords(mat); + } + + private void DisableFlipbook(Material mat) + { + SetFloatIfExists(mat, "_FlipbookBlending", 0f); + + SetKeyword(mat, "_FLIPBOOKBLENDING_ON", false); + } + + private void ClearVatKeywords(Material mat) + { + SetKeyword(mat, "_VAT", false); + SetKeyword(mat, "_VAT_HOUDINI", false); + SetKeyword(mat, "_VAT_TYFLOW", false); + SetHoudiniVATKeyword(mat, -1); + SetTyflowVATKeyword(mat, -1); + } + + private void SetHoudiniVATKeyword(Material mat, int enabledIndex) + { + SetExclusiveKeyword(mat, HoudiniVatKeywords, enabledIndex); + } + + private void SetTyflowVATKeyword(Material mat, int enabledIndex) + { + SetExclusiveKeyword(mat, TyflowVatKeywords, enabledIndex); + } + + private void SetExclusiveKeyword(Material mat, string[] keywords, int enabledIndex) + { + for (int i = 0; i < keywords.Length; i++) + { + SetKeyword(mat, keywords[i], false); + } + + if (enabledIndex >= 0 && enabledIndex < keywords.Length) + { + SetKeyword(mat, keywords[enabledIndex], true); + } + } + + private static void SetFlag(ShaderFlagsBase flags, int flagBits, bool enabled, int index) + { + if (flags == null || + flags.material == null || + flags.CheckFlagBits(flagBits, index: index) == enabled) + { + return; + } + + if (enabled) + { + flags.SetFlagBits(flagBits, index: index); + } + else + { + flags.ClearFlagBits(flagBits, index: index); + } + } + + private struct FlagToggleBinding + { + public readonly string propertyName; + public readonly int flagBits; + public readonly int flagIndex; + + public FlagToggleBinding(string propertyName, int flagBits, int flagIndex) + { + this.propertyName = propertyName; + this.flagBits = flagBits; + this.flagIndex = flagIndex; + } + } + + private struct FlagModeBinding + { + public readonly string propertyName; + public readonly int flagBits; + public readonly int flagIndex; + public readonly int enabledMode; + + public FlagModeBinding(string propertyName, int flagBits, int flagIndex, int enabledMode) + { + this.propertyName = propertyName; + this.flagBits = flagBits; + this.flagIndex = flagIndex; + this.enabledMode = enabledMode; + } + } + } + + public enum VATMode + { + Houdini = 0, + Tyflow = 1, + UnKnownOrMixed = -1 + } + + public enum TimeMode + { + Default = 0, + UnScaleTime = 1, + ScriptableTime = 2 + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderSyncService.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderSyncService.cs.meta new file mode 100644 index 00000000..e334ec2d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/NBShaderSyncService.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 078260ce42a40b046b687b55fa82ae32 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ParticleVertexStreamsItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ParticleVertexStreamsItem.cs new file mode 100644 index 00000000..5139b264 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ParticleVertexStreamsItem.cs @@ -0,0 +1,401 @@ +using System; +using System.Collections.Generic; +using NBShader; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class ParticleVertexStreamsItem : ShaderGUIItem + { + private readonly NBShaderRootItem _nbRootItem; + private readonly List _streams = new List(); + private readonly List _streamNames = new List(); + private readonly List _warnings = new List(); + private readonly List _rendererStreams = new List(); + private readonly List _undoRenderers = new List(); + private WarningMessageCache _rendererWarningMessageCache; + private WarningMessageCache _trailWarningMessageCache; + + public ParticleVertexStreamsItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem) + { + _nbRootItem = rootItem; + } + + public override void OnGUI() + { + if (_nbRootItem.Mats == null || + _nbRootItem.Mats.Count != 1) + { + return; + } + + Material material = _nbRootItem.Mats[0]; + if (material == null) + { + return; + } + + List renderers = _nbRootItem.ParticleRenderersUsingThisMaterial; + if (renderers == null || renderers.Count == 0) + { + return; + } + + NBShaderFlags flags = _nbRootItem.ShaderFlags.Count > 0 + ? _nbRootItem.ShaderFlags[0] as NBShaderFlags + : null; + + if (_nbRootItem.Context.ParticleMode != MixedBool.True) + { + return; + } + + if (flags == null) + { + return; + } + + if (flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER, index: 1)) + { + flags.ClearFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER, index: 1); + } + + BuildExpectedStreams(material, flags, _streams, _streamNames); + + LayoutSpace(); + EditorGUI.LabelField( + ApplyGlobalRectCompensation(LayoutRect()), + NBShaderInspectorLocalization.MakeInspectorContent("vertexStreams.title", "Particle Vertex Streams"), + EditorStyles.boldLabel); + using (new EditorGUI.DisabledScope(true)) + { + for (int i = 0; i < _streamNames.Count; i++) + { + EditorGUI.TextField(ApplyGlobalRectCompensation(LayoutRect()), _streamNames[i]); + } + } + + DrawRendererWarnings(renderers, _streams, false); + +#if UNITY_2022_3_OR_NEWER && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10) + DrawRendererWarnings(renderers, _streams, true); +#endif + } + + private static void BuildExpectedStreams( + Material material, + NBShaderFlags flags, + List streams, + List streamNames) + { + streams.Clear(); + streamNames.Clear(); + + AddStream(streams, streamNames, ParticleSystemVertexStream.Position, "POSITION.xyz"); + + bool useFlipbookBlending = material.IsKeywordEnabled("_FLIPBOOKBLENDING_ON") || + GetFloat(material, "_FlipbookBlending") > 0.5f; + bool useSpecialUVChannel = flags.CheckIsUVModeOn(NBShaderFlags.UVMode.SpecialUVChannel); + bool useUV3ForSpecialUV = flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1); + bool customData1 = flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA1_ON); + bool customData2 = flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA2_ON); + + bool needNormal = GetFloat(material, "_VertexOffset_NormalDir_Toggle") > 0.5f || + GetFloat(material, "_fresnelEnabled") > 0.5f || + GetFloat(material, "_ParallaxMapping_Toggle") > 0.5f || + GetFloat(material, "_FxLightMode") > (float)FxLightMode.UnLit || + GetFloat(material, "_BumpMapToggle") > 0.5f; + bool needTangent = needNormal; + + if (needTangent) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.Tangent, "TANGENT.xyzw"); + } + + if (needNormal) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.Normal, "NORMAL.xyz"); + } + + AddStream(streams, streamNames, ParticleSystemVertexStream.Color, "COLOR.xyzw"); + AddStream(streams, streamNames, ParticleSystemVertexStream.UV, "TEXCOORD0.xy"); + + if (useFlipbookBlending && useSpecialUVChannel) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD0.zw"); + } + else if (useSpecialUVChannel) + { + AddStream(streams, streamNames, useUV3ForSpecialUV ? ParticleSystemVertexStream.UV3 : ParticleSystemVertexStream.UV2, useUV3ForSpecialUV ? "TEXCOORD3.xy" : "TEXCOORD0.zw"); + } + else if (useFlipbookBlending || customData1 || customData2) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD0.zw"); + } + + bool fillSkipUV2 = false; + if (customData1 || customData2 || useFlipbookBlending) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.Custom1XYZW, "TEXCOORD1.xyzw"); + } + else if (useSpecialUVChannel && useUV3ForSpecialUV) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD1.xy"); + fillSkipUV2 = true; + } + + if (customData2 || useFlipbookBlending) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.Custom2XYZW, "TEXCOORD2.xyzw"); + } + else if (useSpecialUVChannel && useUV3ForSpecialUV && !fillSkipUV2) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD2.xy"); + fillSkipUV2 = true; + } + + if (useFlipbookBlending) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.AnimBlend, "TEXCOORD3.x"); + if (useSpecialUVChannel && useUV3ForSpecialUV) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.UV3, "TEXCOORD3.yz"); + } + } + else if (useSpecialUVChannel && useUV3ForSpecialUV && !fillSkipUV2) + { + AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD3.xy"); + } + + AppendVatRequiredStreams(material, streams, streamNames); + } + + private static void AppendVatRequiredStreams(Material material, List streams, List streamNames) + { + if (GetFloat(material, "_VAT_Toggle") <= 0.5f) + { + return; + } + + AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.Position, "VAT POSITION.xyz"); + AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.Normal, "VAT NORMAL.xyz"); + + int vatMode = Mathf.RoundToInt(GetFloat(material, "_VATMode")); + if (vatMode == (int)VATMode.Tyflow) + { + if (IsParticleMode(material) && Mathf.RoundToInt(GetFloat(material, "_TyFlowVATSubMode")) <= 1) + { + AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.UV2, "VAT TEXCOORD0.zw"); + } + + return; + } + + int houdiniSubMode = Mathf.RoundToInt(GetFloat(material, "_HoudiniVATSubMode")); + bool isParticleMode = IsParticleMode(material); + switch (houdiniSubMode) + { + case 0: + AddHoudiniVatUV1Stream(streams, streamNames, isParticleMode); + break; + case 1: + if (isParticleMode) + { + break; + } + + AddHoudiniVatUV1Stream(streams, streamNames, isParticleMode); + AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.Custom2XYZW, "VAT TEXCOORD2.xyzw"); + AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.UV, "VAT TEXCOORD0.xy"); + break; + case 2: + AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.UV, "VAT TEXCOORD0.xy"); + break; + case 3: + AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.UV, "VAT TEXCOORD0.xy"); + AddHoudiniVatUV1Stream(streams, streamNames, isParticleMode); + break; + } + } + + private static void AddHoudiniVatUV1Stream(List streams, List streamNames, bool isParticleMode) + { + AddStreamUnique( + streams, + streamNames, + isParticleMode ? ParticleSystemVertexStream.UV2 : ParticleSystemVertexStream.Custom1XYZW, + isParticleMode ? "VAT TEXCOORD0.zw" : "VAT TEXCOORD1.xyzw"); + } + + private static void AddStream(List streams, List streamNames, ParticleSystemVertexStream stream, string label) + { + streams.Add(stream); + streamNames.Add(label); + } + + private static void AddStreamUnique(List streams, List streamNames, ParticleSystemVertexStream stream, string label) + { + if (streams.Contains(stream)) + { + return; + } + + streams.Add(stream); + streamNames.Add(label); + } + + private static float GetFloat(Material material, string propertyName) + { + return material != null && material.HasProperty(propertyName) ? material.GetFloat(propertyName) : 0f; + } + + private static bool IsParticleMode(Material material) + { + if (material == null || !material.HasProperty("_MeshSourceMode")) + { + return false; + } + + MeshSourceMode meshSourceMode = (MeshSourceMode)Mathf.RoundToInt(material.GetFloat("_MeshSourceMode")); + return meshSourceMode == MeshSourceMode.Particle || meshSourceMode == MeshSourceMode.UIParticle; + } + + private void DrawRendererWarnings(List renderers, List streams, bool trail) + { + _warnings.Clear(); + foreach (ParticleSystemRenderer renderer in renderers) + { + if (renderer == null) + { + continue; + } + + _rendererStreams.Clear(); + if (trail) + { +#if UNITY_2022_3_OR_NEWER && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10) + renderer.GetActiveTrailVertexStreams(_rendererStreams); +#endif + } + else + { + renderer.GetActiveVertexStreams(_rendererStreams); + } + + if (!StreamsEqual(_rendererStreams, streams)) + { + _warnings.Add(renderer.name); + } + } + + if (_warnings.Count == 0) + { + return; + } + + string mismatchText = trail + ? NBShaderInspectorLocalization.GetInspectorText("vertexStreams.trailMismatch", "Particle trail renderers with mismatched vertex streams:") + : NBShaderInspectorLocalization.GetInspectorText("vertexStreams.mismatch", "Particle renderers with mismatched vertex streams:"); + DrawLayoutHelpBox(GetWarningMessage(trail, mismatchText), MessageType.Error); + GUIContent buttonContent = trail + ? NBShaderInspectorLocalization.MakeContent("inspector.vertexStreams.applyTrail.button", "Apply Trail Vertex Streams") + : NBShaderInspectorLocalization.MakeContent("inspector.vertexStreams.apply.button", "Apply Vertex Streams"); + if (GUI.Button(ApplyGlobalRectCompensation(LayoutRect()), buttonContent, EditorStyles.miniButton)) + { + _undoRenderers.Clear(); + for (int i = 0; i < renderers.Count; i++) + { + if (renderers[i] != null) + { + _undoRenderers.Add(renderers[i]); + } + } + + Undo.RecordObjects( + _undoRenderers.ToArray(), + NBShaderInspectorLocalization.GetInspectorText("vertexStreams.apply.undo", "Apply custom vertex streams from material")); + foreach (ParticleSystemRenderer renderer in renderers) + { + if (renderer == null) + { + continue; + } + + if (trail) + { +#if UNITY_2022_3_OR_NEWER && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10) + renderer.SetActiveTrailVertexStreams(streams); +#endif + } + else + { + renderer.SetActiveVertexStreams(streams); + } + } + } + } + + private static bool StreamsEqual(List lhs, List rhs) + { + if (lhs == null || rhs == null || lhs.Count != rhs.Count) + { + return false; + } + + for (int i = 0; i < lhs.Count; i++) + { + if (lhs[i] != rhs[i]) + { + return false; + } + } + + return true; + } + + private string GetWarningMessage(bool trail, string mismatchText) + { + return trail + ? GetWarningMessage(ref _trailWarningMessageCache, mismatchText) + : GetWarningMessage(ref _rendererWarningMessageCache, mismatchText); + } + + private string GetWarningMessage(ref WarningMessageCache cache, string mismatchText) + { + int hash = ComputeWarningsHash(); + if (cache.Message != null && + cache.Count == _warnings.Count && + cache.Hash == hash) + { + return cache.Message; + } + + cache.Count = _warnings.Count; + cache.Hash = hash; + cache.Message = mismatchText + "\n-" + string.Join("\n-", _warnings); + return cache.Message; + } + + private int ComputeWarningsHash() + { + unchecked + { + int hash = 17; + for (int i = 0; i < _warnings.Count; i++) + { + hash = hash * 31 + (_warnings[i] == null ? 0 : StringComparer.Ordinal.GetHashCode(_warnings[i])); + } + + return hash; + } + } + + private struct WarningMessageCache + { + public int Count; + public int Hash; + public string Message; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ParticleVertexStreamsItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ParticleVertexStreamsItem.cs.meta new file mode 100644 index 00000000..7837a97d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/ParticleVertexStreamsItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a9c67414c0e4a938fa58f42f8828e45 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/TABigBlockItem.cs b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/TABigBlockItem.cs new file mode 100644 index 00000000..bc7bd40b --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/TABigBlockItem.cs @@ -0,0 +1,217 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NBShaderEditor +{ + public class TABigBlockItem : BigBlockItem + { + private const string StencilConfigAssetPath = "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/StencilConfig.asset"; + + private readonly NBShaderRootItem _nbRootItem; + private readonly PropertyToggleBlockItem _zOffsetBlock; + private readonly PropertyToggleBlockItem _overrideZBlock; + private readonly RenderQueueItem _renderQueueItem; + private readonly ShaderGUIBitMaskItem _rgbaMaskItem; + private readonly PropertyToggleBlockItem _customStencilBlock; + private readonly BlockItem _keywordBlock; + private StencilValuesConfig _stencilValuesConfig; + + private static readonly string[] RgbaMaskOptions = { "R", "G", "B", "A" }; + + public TABigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) + : base( + rootItem, + parentItem, + "_TABigBlockItemFoldOut", + () => Content("block.ta", "TA Debug", "Technical artist debug and helper controls")) + { + _nbRootItem = rootItem; + + _zOffsetBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_ZOffsetBlockFoldOut", + "_ZOffset_Toggle", + () => Content("ta.zoffset", "Z Offset"), + onValueChanged: OnZOffsetChanged, + isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True, + bold: true); + AddFloat(rootItem, _zOffsetBlock, "_offsetFactor", "Offset Factor"); + AddFloat(rootItem, _zOffsetBlock, "_offsetUnits", "Offset Units"); + + _overrideZBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_OverrideZBlockFoldOut", + "_OverrideZ_Toggle", + () => Content("ta.overrideZ", "Override Z"), + keyword: "_OVERRIDE_Z", + isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True, + bold: true); + AddFloat(rootItem, _overrideZBlock, "_OverrideZValue", "Override Z Value"); + + _renderQueueItem = new RenderQueueItem( + rootItem, + this, + "_QueueBias", + () => Content("ta.renderQueue", "Queue Bias"), + rootItem.SyncService.SyncMaterialState); + + _rgbaMaskItem = new ShaderGUIBitMaskItem( + rootItem, + this, + "_ColorMask", + () => Content("ta.property._ColorMask", "RGBA Mask"), + () => NBShaderInspectorLocalization.GetInspectorOptions("ta.colorMask", RgbaMaskOptions)) + { + ValidMask = 0xF + }; + + _customStencilBlock = new PropertyToggleBlockItem( + rootItem, + this, + "_CustomStencilTestFoldOut", + "_CustomStencilTest", + () => Content("ta.customStencil", "Custom Stencil Test"), + onValueChanged: OnCustomStencilChanged, + bold: true); + new StencilConfigKeyItem(rootItem, _customStencilBlock, this); + AddFloat(rootItem, _customStencilBlock, "_StencilKeyIndex", "Stencil Config Index"); + AddFloat(rootItem, _customStencilBlock, "_Stencil", "Stencil Value"); + AddPopup(rootItem, _customStencilBlock, "_StencilComp", "Stencil Compare", Enum.GetNames(typeof(CompareFunction))); + AddPopup(rootItem, _customStencilBlock, "_StencilOp", "Stencil Operation", Enum.GetNames(typeof(StencilOp))); + AddPopup(rootItem, _customStencilBlock, "_StencilFail", "Stencil Fail", Enum.GetNames(typeof(StencilOp))); + AddPopup(rootItem, _customStencilBlock, "_StencilZFail", "Stencil ZFail", Enum.GetNames(typeof(StencilOp))); + AddFloat(rootItem, _customStencilBlock, "_StencilReadMask", "Stencil Read Mask"); + AddFloat(rootItem, _customStencilBlock, "_StencilWriteMask", "Stencil Write Mask"); + + _keywordBlock = new BlockItem( + rootItem, + this, + "_ShaderKeywordFoldOut", + () => Content("ta.keywords", "Enabled Keywords")); + new KeywordListItem(rootItem, _keywordBlock, () => Content("ta.keywords.list", "Enabled Keywords")); + + InitTriggerByChild(); + } + + public override void DrawBlock() + { + _zOffsetBlock.OnGUI(); + _overrideZBlock.OnGUI(); + _renderQueueItem.OnGUI(); + _rgbaMaskItem.OnGUI(); + _customStencilBlock.OnGUI(); + if (_nbRootItem.Mats.Count == 1) + { + _keywordBlock.OnGUI(); + } + } + + private void OnZOffsetChanged(bool enabled) + { + if (enabled) + { + return; + } + + SetFloat("_offsetFactor", 0f); + SetFloat("_offsetUnits", 0f); + } + + private void OnCustomStencilChanged(bool enabled) + { + if (enabled) + { + return; + } + + _nbRootItem.SyncService.ApplyStencilPreset("ParticleBaseDefault"); + } + + private void SetFloat(string propertyName, float value) + { + for (int i = 0; i < _nbRootItem.Mats.Count; i++) + { + Material mat = _nbRootItem.Mats[i]; + if (mat != null && mat.HasProperty(propertyName)) + { + mat.SetFloat(propertyName, value); + } + } + } + + private string GetStencilKey(int index) + { + _stencilValuesConfig ??= AssetDatabase.LoadAssetAtPath(StencilConfigAssetPath); + return _stencilValuesConfig != null ? _stencilValuesConfig.GetKeyByIndex(index) : string.Empty; + } + + private static void AddFloat(NBShaderRootItem rootItem, ShaderGUIItem parentItem, string propertyName, string label) + { + ShaderGUIFloatItem item = new ShaderGUIFloatItem(rootItem, parentItem) + { + PropertyName = propertyName, + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("ta.property." + propertyName, label) + }; + item.InitTriggerByChild(); + } + + private static void AddPopup(NBShaderRootItem rootItem, ShaderGUIItem parentItem, string propertyName, string label, string[] options) + { + ShaderGUIPopUpItem item = new ShaderGUIPopUpItem(rootItem, parentItem) + { + PropertyName = propertyName, + GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("ta.property." + propertyName, label), + PopUpNames = options + }; + item.InitTriggerByChild(); + } + + private static GUIContent Content(string key, string fallback, string tip = "") + { + return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip); + } + + private sealed class StencilConfigKeyItem : ShaderGUIItem + { + private readonly NBShaderRootItem _nbRootItem; + private readonly TABigBlockItem _owner; + + public StencilConfigKeyItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem, TABigBlockItem owner) + : base(rootItem, parentItem) + { + _nbRootItem = rootItem; + _owner = owner; + } + + public override void OnGUI() + { + if (!_nbRootItem.PropertyInfoDic.TryGetValue("_StencilKeyIndex", out ShaderPropertyInfo info)) + { + return; + } + + string key = string.Empty; + bool hasMixedValue = info.Property.hasMixedValue; + if (!hasMixedValue) + { + key = _owner.GetStencilKey(Mathf.RoundToInt(info.Property.floatValue)); + } + + EditorGUI.showMixedValue = hasMixedValue; + using (new EditorGUI.DisabledScope(true)) + { + EditorGUI.TextField( + ApplyGlobalRectCompensation(LayoutRect()), + NBShaderInspectorLocalization.GetInspectorText("ta.stencil.currentConfig", "当前Config:"), + key); + } + + EditorGUI.showMixedValue = false; + } + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/TABigBlockItem.cs.meta b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/TABigBlockItem.cs.meta new file mode 100644 index 00000000..aadb0e2e --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/ShaderGUIItems/TABigBlockItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17025a3939882e0459ded7a5251b2463 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Editor/com.xuanxuan.nb.shaders2.Editor.asmdef b/Packages/NB_FX/NBShaders2/Editor/com.xuanxuan.nb.shaders2.Editor.asmdef new file mode 100644 index 00000000..e0b89d42 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/com.xuanxuan.nb.shaders2.Editor.asmdef @@ -0,0 +1,20 @@ +{ + "name": "com.xuanxuan.nb.shaders2.Editor", + "rootNamespace": "", + "references": [ + "GUID:8495541fcd41b0c40b5b6e6e7a7639d1", + "GUID:8f9e4d586616f13449cfeb86c5f704c2", + "GUID:aed681b6b9e69ff4dbd8d55e012b87ff" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Packages/NB_FX/NBShaders2/Editor/com.xuanxuan.nb.shaders2.Editor.asmdef.meta b/Packages/NB_FX/NBShaders2/Editor/com.xuanxuan.nb.shaders2.Editor.asmdef.meta new file mode 100644 index 00000000..28622afa --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Editor/com.xuanxuan.nb.shaders2.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6e0dde26488c0e44a9afcddc82a907e9 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime.meta b/Packages/NB_FX/NBShaders2/Runtime.meta new file mode 100644 index 00000000..d1bbdca5 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a21852943b9bc9840919005d3eb6dcc9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureCatalog.cs b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureCatalog.cs new file mode 100644 index 00000000..ed99b3e9 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureCatalog.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; + +namespace NBShader +{ + /// + /// Hard-coded catalog of raw shader feature keywords managed by the NBShader runtime tier system. + /// Keywords not listed here are never changed by . + /// + public static class NBShaderFeatureCatalog + { + /// + /// Shader name used by NBShader materials. + /// + public const string ShaderName = "Effects/NBShader"; + + /// + /// Default file name for optional NBShader runtime settings assets. + /// User projects decide how those assets are loaded at runtime. + /// + public const string RuntimeSettingsAssetName = "NBShaderFeatureRuntimeSettings"; + + /// + /// Raw shader_feature keywords currently managed by NBShader tiering. The '_' placeholder and + /// multi_compile keywords are intentionally excluded. + /// + public static readonly string[] RawKeywords = + { + "NB_DEBUG_DISSOLVE", + "NB_DEBUG_DISTORT", + "NB_DEBUG_FRESNEL", + "NB_DEBUG_MASK", + "NB_DEBUG_PNOISE", + "NB_DEBUG_VERTEX_OFFSET", + "VFX_SIX_WAY_ABSORPTION", + "_ALPHAMODULATE_ON", + "_ALPHAPREMULTIPLY_ON", + "_ALPHATEST_ON", + "_CHROMATIC_ABERRATION", + "_COLORMAPBLEND", + "_COLOR_RAMP", + "_COLOR_RAMP_MAP", + "_DEPTH_DECAL", + "_DEPTH_OUTLINE", + "_DISSOLVE", + "_DISSOLVE_MASK", + "_DISSOLVE_RAMP", + "_DISSOLVE_RAMP_MAP", + "_DISTANCE_FADE", + "_DISTORT_REFRACTION", + "_EMISSION", + "_FLIPBOOKBLENDING_ON", + "_FRESNEL", + "_FX_LIGHT_MODE_BLINN_PHONG", + "_FX_LIGHT_MODE_HALF_LAMBERT", + "_FX_LIGHT_MODE_PBR", + "_FX_LIGHT_MODE_SIX_WAY", + "_FX_LIGHT_MODE_UNLIT", + "_HOUDINI_VAT_DYNAMIC_REMESH", + "_HOUDINI_VAT_PARTICLE_SPRITE", + "_HOUDINI_VAT_RIGIDBODY", + "_HOUDINI_VAT_SOFTBODY", + "_MASKMAP_ON", + "_MASKMAP2_ON", + "_MASKMAP3_ON", + "_MATCAP", + "_NOISEMAP", + "_NOISE_MASKMAP", + "_NORMALMAP", + "_OVERRIDE_Z", + "_PARALLAX_MAPPING", + "_PARCUSTOMDATA_ON", + "_PROGRAM_NOISE", + "_PROGRAM_NOISE_SIMPLE", + "_PROGRAM_NOISE_VORONOI", + "_SCREEN_DISTORT_MODE", + "_SCRIPTABLETIME", + "_SHARED_UV", + "_SOFTPARTICLES_ON", + "_SPECULAR_COLOR", + "_STENCIL_WITHOUT_PLAYER", + "_TYFLOW_VAT_ABSOLUTE", + "_TYFLOW_VAT_RELATIVE", + "_TYFLOW_VAT_SKIN_PR", + "_TYFLOW_VAT_SKIN_PRSAVE", + "_TYFLOW_VAT_SKIN_PRSXYZ", + "_TYFLOW_VAT_SKIN_R", + "_UNSCALETIME", + "_VAT", + "_VAT_HOUDINI", + "_VAT_TYFLOW", + "_VERTEX_OFFSET", + "_VERTEX_OFFSET_MASKMAP" + }; + + internal static readonly HashSet RawKeywordSet = new HashSet(RawKeywords); + + /// + /// Returns true when the keyword is explicitly managed by the NBShader feature tier system. + /// Catalog-external keywords must be ignored by tier application and build stripping. + /// + public static bool IsManagedKeyword(string keyword) + { + return !string.IsNullOrEmpty(keyword) && RawKeywordSet.Contains(keyword); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureCatalog.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureCatalog.cs.meta new file mode 100644 index 00000000..9ee4168d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureCatalog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: faf1ed0560444790b66010208bd2934f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntime.cs b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntime.cs new file mode 100644 index 00000000..8931d66d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntime.cs @@ -0,0 +1,183 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NBShader +{ + /// + /// Runtime API for applying NBShader feature tiers to materials. + /// + public static class NBShaderFeatureRuntime + { + /// + /// Applies an NBShader feature tier to one material in place. Only materials whose shader name is + /// "Effects/NBShader" are processed. Managed Catalog keywords and shader passes are derived from + /// serialized material intent, then filtered by the target tier. + /// + /// Material to process. Null materials are ignored. + /// + /// Target tier. When null, Ultra is used. This overload does not load runtime settings, so it keeps all + /// managed Catalog keywords and pass features available. + /// + /// + /// If lower-tier shader variants have been stripped from the build, call this API before the material is + /// used for rendering. Otherwise Unity can request a missing variant and select a similar available variant. + /// + public static void ApplyTier(Material material, NBShaderFeatureTier? tier = null) + { + ApplyTierInternal(material, null, tier); + } + + /// + /// Applies an NBShader feature tier using a user-loaded runtime settings asset. + /// Pass null for to resolve the tier from the settings quality mapping. + /// + public static void ApplyTier(Material material, NBShaderFeatureRuntimeSettings settings, NBShaderFeatureTier? tier) + { + ApplyTierInternal(material, settings, tier); + } + + /// + /// Applies an NBShader feature tier to multiple materials in place. Only materials whose shader name is + /// "Effects/NBShader" are processed. Catalog-external keywords are left unchanged unless they are + /// explicitly tied to a managed NBShader feature. + /// + /// Materials to process. Null collections and null entries are ignored. + /// + /// Target tier. When null, Ultra is used. This overload does not load runtime settings, so it keeps all + /// managed Catalog keywords and pass features available. + /// + /// + /// If lower-tier shader variants have been stripped from the build, call this API before the materials are + /// used for rendering. Otherwise Unity can request a missing variant and select a similar available variant. + /// + public static void ApplyTier(IEnumerable materials, NBShaderFeatureTier? tier = null) + { + ApplyTierInternal(materials, null, tier); + } + + /// + /// Applies an NBShader feature tier to multiple materials using a user-loaded runtime settings asset. + /// Pass null for to resolve the tier from the settings quality mapping. + /// + public static void ApplyTier(IEnumerable materials, NBShaderFeatureRuntimeSettings settings, NBShaderFeatureTier? tier) + { + ApplyTierInternal(materials, settings, tier); + } + + private static void ApplyTierInternal(IEnumerable materials, NBShaderFeatureRuntimeSettings settings, NBShaderFeatureTier? tier) + { + if (materials == null) + { + return; + } + + foreach (Material material in materials) + { + ApplyTierInternal(material, settings, tier); + } + } + + private static void ApplyTierInternal(Material material, NBShaderFeatureRuntimeSettings settings, NBShaderFeatureTier? tier) + { + if (!IsNBShaderMaterial(material)) + { + return; + } + + NBShaderFeatureTier resolvedTier = tier.HasValue ? tier.Value : ResolveTierFromQuality(settings); + HashSet allowed = settings != null + ? settings.BuildAllowedSet(resolvedTier) + : BuildAllowAllCatalogKeywordSet(); + HashSet allowedPassFeatures = settings != null + ? settings.BuildAllowedPassFeatureSet(resolvedTier) + : null; + NBShaderMaterialIntentResult result = NBShaderMaterialIntentResolver.Resolve(material, resolvedTier, allowed, allowedPassFeatures); + ApplyResolvedIntent(material, result); + } + + private static bool IsNBShaderMaterial(Material material) + { + return material != null + && material.shader != null + && material.shader.name == NBShaderFeatureCatalog.ShaderName; + } + + private static void ApplyResolvedIntent(Material material, NBShaderMaterialIntentResult result) + { + if (material == null || result == null) + { + return; + } + + var effectiveKeywords = new HashSet(result.effectiveKeywords); + for (int i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++) + { + string keyword = NBShaderFeatureCatalog.RawKeywords[i]; + bool shouldEnable = effectiveKeywords.Contains(keyword); + if (material.IsKeywordEnabled(keyword) != shouldEnable) + { + if (shouldEnable) + { + material.EnableKeyword(keyword); + } + else + { + material.DisableKeyword(keyword); + } + } + } + + bool evaluateShVertex = effectiveKeywords.Contains("_FX_LIGHT_MODE_SIX_WAY"); + if (material.IsKeywordEnabled("EVALUATE_SH_VERTEX") != evaluateShVertex) + { + if (evaluateShVertex) + { + material.EnableKeyword("EVALUATE_SH_VERTEX"); + } + else + { + material.DisableKeyword("EVALUATE_SH_VERTEX"); + } + } + + for (int i = 0; i < result.passes.Length; i++) + { + NBShaderPassIntent pass = result.passes[i]; + if (!string.IsNullOrEmpty(pass.passName) && + material.GetShaderPassEnabled(pass.passName) != pass.included) + { + material.SetShaderPassEnabled(pass.passName, pass.included); + } + } + } + + private static NBShaderFeatureTier ResolveTierFromQuality(NBShaderFeatureRuntimeSettings settings) + { + if (settings == null) + { + return NBShaderFeatureTier.Ultra; + } + + string qualityName = GetCurrentQualityName(); + NBShaderFeatureTier tier; + return settings.TryGetTierForQualityName(qualityName, out tier) ? tier : NBShaderFeatureTier.Ultra; + } + + private static string GetCurrentQualityName() + { + string[] names = QualitySettings.names; + int index = QualitySettings.GetQualityLevel(); + if (names != null && index >= 0 && index < names.Length) + { + return names[index]; + } + + return string.Empty; + } + + private static HashSet BuildAllowAllCatalogKeywordSet() + { + return new HashSet(NBShaderFeatureCatalog.RawKeywords); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntime.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntime.cs.meta new file mode 100644 index 00000000..220d3954 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntime.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6115ddf8278414a953d467dc43f637c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntimeSettings.cs b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntimeSettings.cs new file mode 100644 index 00000000..b3cc8710 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntimeSettings.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NBShader +{ + /// + /// Optional runtime settings for NBShader feature tiering. User projects own asset creation and + /// runtime loading; pass the loaded asset to when tier gating is required. + /// + [CreateAssetMenu(fileName = NBShaderFeatureCatalog.RuntimeSettingsAssetName, menuName = "NBShader/Feature Runtime Settings")] + public sealed class NBShaderFeatureRuntimeSettings : ScriptableObject + { + [Serializable] + public sealed class QualityTierMapping + { + public string qualityName; + public NBShaderFeatureTier tier = NBShaderFeatureTier.Ultra; + } + + [Header("Allowed Raw Shader Feature Keywords")] + public string[] lowAllowedKeywords = CloneCatalogKeywords(); + public string[] mediumAllowedKeywords = CloneCatalogKeywords(); + public string[] highAllowedKeywords = CloneCatalogKeywords(); + public string[] ultraAllowedKeywords = CloneCatalogKeywords(); + + [Header("Allowed Shader Pass Features")] + public string[] lowAllowedPassFeatures = CloneCatalogPassFeatures(); + public string[] mediumAllowedPassFeatures = CloneCatalogPassFeatures(); + public string[] highAllowedPassFeatures = CloneCatalogPassFeatures(); + public string[] ultraAllowedPassFeatures = CloneCatalogPassFeatures(); + + [Header("QualitySettings Name To Tier")] + public QualityTierMapping[] qualityTierMappings = new QualityTierMapping[0]; + + public string[] GetAllowedKeywords(NBShaderFeatureTier tier) + { + switch (tier) + { + case NBShaderFeatureTier.Low: + return lowAllowedKeywords ?? NBShaderFeatureCatalog.RawKeywords; + case NBShaderFeatureTier.Medium: + return mediumAllowedKeywords ?? NBShaderFeatureCatalog.RawKeywords; + case NBShaderFeatureTier.High: + return highAllowedKeywords ?? NBShaderFeatureCatalog.RawKeywords; + default: + return ultraAllowedKeywords ?? NBShaderFeatureCatalog.RawKeywords; + } + } + + public string[] GetAllowedPassFeatures(NBShaderFeatureTier tier) + { + switch (tier) + { + case NBShaderFeatureTier.Low: + return lowAllowedPassFeatures ?? NBShaderPassFeatureCatalog.RawPassFeatureIds; + case NBShaderFeatureTier.Medium: + return mediumAllowedPassFeatures ?? NBShaderPassFeatureCatalog.RawPassFeatureIds; + case NBShaderFeatureTier.High: + return highAllowedPassFeatures ?? NBShaderPassFeatureCatalog.RawPassFeatureIds; + default: + return ultraAllowedPassFeatures ?? NBShaderPassFeatureCatalog.RawPassFeatureIds; + } + } + + public bool TryGetTierForQualityName(string qualityName, out NBShaderFeatureTier tier) + { + tier = NBShaderFeatureTier.Ultra; + if (string.IsNullOrEmpty(qualityName) || qualityTierMappings == null) + { + return false; + } + + for (int i = 0; i < qualityTierMappings.Length; i++) + { + QualityTierMapping mapping = qualityTierMappings[i]; + if (mapping != null && string.Equals(mapping.qualityName, qualityName, StringComparison.OrdinalIgnoreCase)) + { + tier = mapping.tier; + return true; + } + } + + return false; + } + + internal HashSet BuildAllowedSet(NBShaderFeatureTier tier) + { + string[] keywords = GetAllowedKeywords(tier); + HashSet allowed = new HashSet(); + for (int i = 0; i < keywords.Length; i++) + { + string keyword = keywords[i]; + if (NBShaderFeatureCatalog.IsManagedKeyword(keyword)) + { + allowed.Add(keyword); + } + } + + return allowed; + } + + internal HashSet BuildAllowedPassFeatureSet(NBShaderFeatureTier tier) + { + string[] passFeatures = GetAllowedPassFeatures(tier); + HashSet allowed = new HashSet(); + for (int i = 0; i < passFeatures.Length; i++) + { + string passFeature = passFeatures[i]; + if (NBShaderPassFeatureCatalog.IsManagedPassFeature(passFeature)) + { + allowed.Add(passFeature); + } + } + + return allowed; + } + + private static string[] CloneCatalogKeywords() + { + return (string[])NBShaderFeatureCatalog.RawKeywords.Clone(); + } + + private static string[] CloneCatalogPassFeatures() + { + return (string[])NBShaderPassFeatureCatalog.RawPassFeatureIds.Clone(); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntimeSettings.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntimeSettings.cs.meta new file mode 100644 index 00000000..9ff297d1 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureRuntimeSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c77ae8665b4443efa5ab2f470a2939b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureTier.cs b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureTier.cs new file mode 100644 index 00000000..6c411562 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureTier.cs @@ -0,0 +1,13 @@ +namespace NBShader +{ + /// + /// Runtime NBShader feature tiers, ordered from the smallest keyword budget to the full feature set. + /// + public enum NBShaderFeatureTier + { + Low = 0, + Medium = 1, + High = 2, + Ultra = 3 + } +} diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureTier.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureTier.cs.meta new file mode 100644 index 00000000..f909913a --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFeatureTier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0ad18474c2a04675834e005ab993b7c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFlags.cs b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFlags.cs new file mode 100644 index 00000000..1647030d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFlags.cs @@ -0,0 +1,773 @@ +using UnityEngine; + +namespace NBShader +{ + public class NBShaderFlags : ShaderFlagsBase + { + public const string FlagsName = "_W9ParticleShaderFlags"; + public static int FlagsId = Shader.PropertyToID(FlagsName); + + + public const string Flags1Name = "_W9ParticleShaderFlags1"; + public static int Flags1Id = Shader.PropertyToID(Flags1Name); + + public const string WrapFlagsName = "_W9ParticleShaderWrapFlags"; + public static int WrapFlagsId = Shader.PropertyToID(WrapFlagsName); + + public const string foldOutFlagName = "_NBShaderGUIFoldToggle"; + public static int foldOutFlagId = Shader.PropertyToID(foldOutFlagName); + + public const string foldOutFlagName1 = "_NBShaderGUIFoldToggle1"; + public static int foldOutFlagId1 = Shader.PropertyToID(foldOutFlagName1); + + public const string foldOutFlagName2 = "_NBShaderGUIFoldToggle2"; + public static int foldOutFlagId2 = Shader.PropertyToID(foldOutFlagName2); + + public const string colorChannelFlagName = "_W9ParticleShaderColorChannelFlag"; + public static int colorChannelFlagId = Shader.PropertyToID(colorChannelFlagName); + + public const string pNoiseBlendFlagName = "_W9ParticleShaderPNoiseBlendFlag"; + public static int pNoiseBlendFlagId = Shader.PropertyToID(pNoiseBlendFlagName); + + // public const string WrapFlags2Name = "_W9ParticleShaderWrapFlags2"; + // public static int WrapFlags2Id = Shader.PropertyToID(WrapFlags2Name); + + public override int GetShaderFlagsId(int index = 0) + { + switch (index) + { + case 0: + return FlagsId; + + case 1: + return Flags1Id; + + case 2: + return WrapFlagsId; + + //FoldOut必须要紧挨着,因为按照Index去拿AnimBool + case 3: + return foldOutFlagId; + + case 4: + return foldOutFlagId1; + + case 5: + return foldOutFlagId2; + + case 6: + return colorChannelFlagId; + + case 7: + return pNoiseBlendFlagId; + // case 8: + // return WrapFlags2Id; + + default: + return FlagsId; + } + } + + protected override string GetShaderFlagsName(int index = 0) + { + switch (index) + { + case 0: + return FlagsName; + + case 1: + return Flags1Name; + + case 2: + return WrapFlagsName; + + case 3: + return foldOutFlagName; + + case 4: + return foldOutFlagName1; + + case 5: + return colorChannelFlagName; + + default: + return FlagsName; + } + } + + + + + + public NBShaderFlags(Material material = null) : base(material) + { + } + + public const int FLAG_BIT_SATURABILITY_ON = 1 << 0; + public const int FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE = 1 << 1; + public const int FLAG_BIT_PARTICLE_FRESNEL_FADE_ON = 1 << 2; + public const int FLAG_BIT_PARTICLE_FRESNEL_COLOR_ON = 1 << 3; + public const int FLAG_BIT_PARTICLE_USETEXCOORD2 = 1 << 4; + // public const int FLAG_BIT_PARTICLE_DISTANCEFADE_ON = 1 << 5; // Obsolete/reserved: keyword-driven (_DISTANCE_FADE). + // public const int FLAG_BIT_PARTICLE_CHORATICABERRAT = 1 << 6; // Obsolete/reserved: keyword-driven (_CHROMATIC_ABERRATION). + public const int FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON = 1 << 7; + public const int FLAG_BIT_PARTICLE_POLARCOORDINATES_ON = 1 << 8; + public const int FLAG_BIT_PARTICLE_UTWIRL_ON = 1 << 9; + public const int FLAG_BIT_PARTICLE_LINEARTOGAMMA_ON = 1 << 10; + // public const int FLAG_BIT_PARTICLE_FRESNEL_ON = 1 << 11; // Obsolete/reserved: keyword-driven (_FRESNEL). + public const int FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON = 1 << 12; + public const int FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA = 1 << 13; + public const int FLAG_BIT_PARTICLE_UIEFFECT_ON = 1 << 14; + public const int FLAG_BIT_PARTICLE_UNSCALETIME_ON = 1 << 15; + public const int FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON = 1 << 16; + public const int FLAG_BIT_PARTICLE_CUSTOMDATA1_ON = 1 << 17; + public const int FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON = 1 << 18; + public const int FLAG_BIT_HUESHIFT_ON = 1 << 19; + public const int FLAG_BIT_PARTICLE_CUSTOMDATA2_ON = 1 << 20; + public const int FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE = 1 << 21; + public const int FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX = 1 << 22; + // public const int FLAG_BIT_PARTICLE_RAMP_COLOR_MAP_MODE_ON = 1 << 23; // Obsolete/reserved: keyword-driven (_COLOR_RAMP_MAP). + public const int FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD = 1 << 24; + public const int FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE = 1 << 25; + // public const int FLAG_BIT_PARTICLE_DISSOLVE_RAMP_MAP = 1 << 26; // Obsolete/reserved: keyword-driven (_DISSOLVE_RAMP_MAP). + // public const int FLAG_BIT_PARTICLE_DISSOLVE_MASK = 1 << 27; // Obsolete/reserved: keyword-driven (_DISSOLVE_MASK). + public const int FLAG_BIT_PARTICLE_BACKCOLOR = 1 << 28; + public const int FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA = 1 << 29; + // public const int FLAG_BIT_PARTICLE_VERTEX_OFFSET_ON = 1 << 30; // Obsolete/reserved: keyword-driven (_VERTEX_OFFSET). + public const int FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR = 1 << 31; + + public const int FLAG_BIT_PARTICLE_1_TRANSPARENT_MODE = 1 << 0; + public const int FLAG_BIT_PARTICLE_1_TRANSPARENT_SHADOW_DITHER = 1 << 1; + public const int FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT = 1 << 2; + public const int FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT = 1 << 3; + public const int FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT = 1 << 4; + public const int FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK = 1 << 5; + public const int FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY = 1 << 6; + public const int FLAG_BIT_PARTICLE_1_MASK_REFINE = 1 << 7; + public const int FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE = 1 << 8; + public const int FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR = 1 << 9; + // public const int FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE = 1 << 10; // Obsolete/reserved: keyword-driven (_PROGRAM_NOISE_SIMPLE). + // public const int FLAG_BIT_PARTICLE_1_DISSOVLE_USE_RAMP = 1 << 11; // Obsolete/reserved: keyword-driven (_DISSOLVE_RAMP). + // public const int FLAG_BIT_PARTICLE_1_MASK_MAP2 = 1 << 12; // Obsolete/reserved: keyword-driven (_MASKMAP2_ON). + // public const int FLAG_BIT_PARTICLE_1_MASK_MAP3 = 1 << 13; // Obsolete/reserved: keyword-driven (_MASKMAP3_ON). + // public const int FLAG_BIT_PARTICLE_1_NOISE_MASKMAP = 1 << 14; // Obsolete/reserved: keyword-driven (_NOISE_MASKMAP). + public const int FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER = 1 << 15; + // public const int FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI = 1 << 16; // Obsolete/reserved: keyword-driven (_PROGRAM_NOISE_VORONOI). + public const int FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE = 1 << 17; + public const int FLAG_BIT_PARTICLE_1_USE_TEXCOORD1 = 1 << 18; + public const int FLAG_BIT_PARTICLE_1_USE_TEXCOORD2 = 1 << 19; + public const int FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE = 1 << 20; + public const int FLAG_BIT_PARTICLE_1_UV_FROM_MESH = 1 << 21; //3D条件下,如果不是来源于Mesh,就默认来源于粒子。 + public const int FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE = 1 << 22; //3D条件下,如果不是来源于Mesh,就默认来源于粒子。 + public const int FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM = 1 << 23; //3D条件下,如果不是来源于Mesh,就默认来源于粒子。 + public const int FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST = 1 << 24; + public const int FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO = 1 << 25; + // public const int FLAG_BIT_PARTICLE_1_VERTEXOFFSET_MASKMAP = 1 << 26; // Obsolete/reserved: keyword-driven (_VERTEX_OFFSET_MASKMAP). + public const int FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE = 1 << 27; + public const int FLAG_BIT_PARTICLE_1_BUMP_TEX_UV_FOLLOW_MAINTEX = 1 << 28; + public const int FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP = 1 << 29; + public const int FLAG_BIT_PARTICLE_1_MATCAP_MULTY_MODE = 1 << 30; + + + public const int FLAG_BIT_WRAPMODE_BASEMAP = 1 << 0; + public const int FLAG_BIT_WRAPMODE_MASKMAP = 1 << 1; + public const int FLAG_BIT_WRAPMODE_MASKMAP2 = 1 << 2; + public const int FLAG_BIT_WRAPMODE_NOISEMAP = 1 << 3; + public const int FLAG_BIT_WRAPMODE_EMISSIONMAP = 1 << 4; + public const int FLAG_BIT_WRAPMODE_DISSOLVE_MAP = 1 << 5; + public const int FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP = 1 << 6; + public const int FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP = 1 << 7; + public const int FLAG_BIT_WRAPMODE_COLORBLENDMAP = 1 << 8; + public const int FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP = 1 << 9; + public const int FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP = 1 << 10; + public const int FLAG_BIT_WRAPMODE_MASKMAP3 = 1 << 11; + public const int FLAG_BIT_WRAPMODE_NOISE_MASKMAP = 1 << 12; + public const int FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP = 1 << 13; + public const int FLAG_BIT_WRAPMODE_BUMPTEX = 1 << 14; + public const int FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP = 1 << 15; + + // public const int FLAG_BIT_WRAPMODE2_SHAREDUV = 1 << 0; + + public const int foldOutBitMeshOption = 1 << 0; + public const int foldOutBitMainTexOption = 1 << 1; + public const int foldOutBitBaseOption = 1 << 2; + public const int foldOutBitFeatureOption = 1 << 3; + public const int foldOutBitBaseMap = 1 << 4; + public const int foldOutBitMask = 1 << 5; + public const int foldOutBitMaskMap = 1 << 6; + public const int foldOutBitMask2 = 1 << 7; + public const int foldOutBitMask3 = 1 << 8; + public const int foldOutBitTwril = 1 << 9; + public const int foldOutBitPolar = 1 << 10; + public const int foldOutBitHueShift = 1 << 11; + public const int foldOutBitSaturability = 1 << 12; + public const int foldOutBitDistanceFade = 1 << 13; + public const int foldOutBitSoftParticles = 1 << 14; + public const int foldOutBitMaskRotate = 1 << 15; + public const int foldOutBitNoise = 1 << 16; + public const int foldOutBitNoiseMap = 1 << 17; + public const int foldOutBitNoiseMaskToggle = 1 << 18; + public const int foldOutBitEmission = 1 << 19; + public const int foldOutBitDistortionChoraticaberrat = 1 << 20; + public const int foldOutDissolve = 1 << 21; + public const int foldOutDissolveMap = 1 << 22; + public const int foldOutProgramNoise = 1 << 23; + public const int foldOutDissolveRampMap = 1 << 24; + public const int foldOutDissolveMask = 1 << 25; + public const int foldOutColorBlend = 1 << 26; + public const int foldOutFresnel = 1 << 27; + public const int foldOutDepthOutline = 1 << 28; + public const int foldOutVertexOffset = 1 << 29; + public const int foldOutParallexMapping = 1 << 30; + // public const int foldOutBit1Portal= 1 << 31; + + + + + public const int foldOutBit1UVModeMainTex = 1 << 0; + public const int foldOutBit1UVModeMaskMap = 1 << 1; + public const int foldOutBit1UVModeMaskMap2 = 1 << 2; + public const int foldOutBit1UVModeMaskMap3 = 1 << 3; + public const int foldOutBit1UVModeNoiseMap = 1 << 4; + public const int foldOutBit1UVModeNoiseMaskMap = 1 << 5; + public const int foldOutBit1UVModeEmissionMap = 1 << 6; + public const int foldOutBit1UVModeDissolveMap = 1 << 7; + public const int foldOutBit1UVModeDissolveMaskMap = 1 << 8; + public const int foldOutBit1UVModeColorBlendMap = 1 << 9; + public const int foldOutBit1UVModeVertexOffsetMap = 1 << 10; + public const int foldOutBit1UVModeVertexOffsetMaskMap = 1 << 11; + public const int foldOutBit1UVModeBumpTex = 1 << 12; + public const int foldOutBit1UVModeRampColorMap = 1 << 13; + public const int foldOutBit1UVModeProgramNoise = 1 << 14; + + //留一些位置给以后可能会增加的贴图。 + public const int foldOutBit1Portal = 1 << 20; + public const int foldOutBit1ZOffset = 1 << 21; + public const int foldOutBit1CustomStencilTest = 1 << 22; + public const int foldOutBit1TaOption = 1 << 23; + public const int foldOutBit1MianTexContrast = 1 << 24; + public const int foldOutBit1VertexOffsetMask = 1 << 25; + public const int foldOutBit1MainTexColorRefine = 1 << 26; + public const int foldOutBit1LightOption = 1 << 27; + public const int foldOutBit1ShaderKeyword = 1 << 28; + public const int foldOutBit1BumpTex = 1 << 29; + + public const int foldOutBit2BumpTexToggle = 1 << 0; + public const int foldOutBit2MatCapToggle = 1 << 1; + public const int foldOutBit2RampColor = 1 << 2; + public const int foldOutBit2DissolveLine = 1 << 3; + public const int foldOutBit2BaseBackColor = 1 << 4; + public const int foldOutBit2MaskRefine = 1 << 5; + public const int foldOutBit2ScreenDistortAlphaRefine = 1 << 6; + public const int foldOutBit2ProgramNoiseSimple = 1 << 7; + public const int foldOutBit2ProgramNoiseVoronoi = 1 << 8; + public const int foldOutBit2ColorAdjustment = 1 << 9; + public const int foldOutBit2SharedUV = 1 << 10; + public const int foldOutBit2SharedUVMode = 1 << 11; + public const int foldOutBit2VAT = 1 << 12; + + + #region CustomDataCodes + + public const string CustomDataFlag0Name = "_W9ParticleCustomDataFlag0"; + public const string CustomDataFlag1Name = "_W9ParticleCustomDataFlag1"; + public const string CustomDataFlag2Name = "_W9ParticleCustomDataFlag2"; + public const string CustomDataFlag3Name = "_W9ParticleCustomDataFlag3"; + public static int CustomDataFlag0Id = Shader.PropertyToID(CustomDataFlag0Name); + public static int CustomDataFlag1Id = Shader.PropertyToID(CustomDataFlag1Name); + public static int CustomDataFlag2Id = Shader.PropertyToID(CustomDataFlag2Name); + public static int CustomDataFlag3Id = Shader.PropertyToID(CustomDataFlag3Name); + + public enum CutomDataComponent + { + Off, + CustomData1X, + CustomData1Y, + CustomData1Z, + CustomData1W, + CustomData2X, + CustomData2Y, + CustomData2Z, + CustomData2W, + UnKnownOrMixed = -1 + } + + public const int FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X = 0 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y = 1 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY = 2 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT = 3 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X = 4 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y = 5 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET = 6 * 4; + public const int FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY = 7 * 4; + + public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X = 0 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y = 1 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY = 2 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_SATURATE = 3 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X = 4 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y = 5 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY = 6 * 4; + public const int FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY = 7 * 4; + + public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X = 0 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y = 1 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X = 2 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y = 3 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X = 4 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y = 5 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST = 6 * 4; + public const int FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME = 7 * 4; + + public const int FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X = 0 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y = 1 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X = 2 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y = 3 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X = 4 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y = 5 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X = 6 * 4; + public const int FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y = 7 * 4; + + + public const int isCustomDataBit = 1 << 3; + public const int Data12Bit = 1 << 2; //true CustomData1 / false CustomData2 + public const int DataXYorZWBit = 1 << 1; //true xy / false zw + public const int DataXZorYWBit = 1 << 0; //true xz / false yw + public const int CustomData1XBit = isCustomDataBit | Data12Bit | DataXYorZWBit | DataXZorYWBit; + public const int CustomData1YBit = isCustomDataBit | Data12Bit | DataXYorZWBit; + public const int CustomData1ZBit = isCustomDataBit | Data12Bit | DataXZorYWBit; + public const int CustomData1WBit = isCustomDataBit | Data12Bit; + public const int CustomData2XBit = isCustomDataBit | DataXYorZWBit | DataXZorYWBit; + public const int CustomData2YBit = isCustomDataBit | DataXYorZWBit; + public const int CustomData2ZBit = isCustomDataBit | DataXZorYWBit; + public const int CustomData2WBit = isCustomDataBit; + + private int GetCustomDataFlagID(int dataIndex) + { + switch (dataIndex) + { + case 0: + return CustomDataFlag0Id; + + case 1: + return CustomDataFlag1Id; + + case 2: + return CustomDataFlag2Id; + case 3: + return CustomDataFlag3Id; + + } + + return 0; + } + + public string GetCustomDataFlagPropertyName(int dataIndex) + { + switch (dataIndex) + { + case 0: + return CustomDataFlag0Name; + + case 1: + return CustomDataFlag1Name; + + case 2: + return CustomDataFlag2Name; + + case 3: + return CustomDataFlag3Name; + + } + + return null; + } + + public CutomDataComponent GetCustomDataFlag(int dataBitPos, int dataIndex) + { + int bit = material.GetInteger(GetCustomDataFlagID(dataIndex)); + + bit = bit >> dataBitPos; + bit &= 15; // binary 1111 + + if ((bit & isCustomDataBit) == 0) + { + return CutomDataComponent.Off; + } + else if (bit == CustomData1XBit) + { + return CutomDataComponent.CustomData1X; + } + else if (bit == CustomData1YBit) + { + return CutomDataComponent.CustomData1Y; + } + else if (bit == CustomData1ZBit) + { + return CutomDataComponent.CustomData1Z; + } + else if (bit == CustomData1WBit) + { + return CutomDataComponent.CustomData1W; + } + else if (bit == CustomData2XBit) + { + return CutomDataComponent.CustomData2X; + } + else if (bit == CustomData2YBit) + { + return CutomDataComponent.CustomData2Y; + } + else if (bit == CustomData2ZBit) + { + return CutomDataComponent.CustomData2Z; + } + else if (bit == CustomData2WBit) + { + return CutomDataComponent.CustomData2W; + } + else + { + } + + Debug.Log("不可能存在的情况"); + return CutomDataComponent.Off; + + } + + public void SetCustomDataFlag(CutomDataComponent cutomDataComponent, int dataBitPos, int dataIndex) + { + int bit = 0; + switch (cutomDataComponent) + { + case CutomDataComponent.Off: + bit = 0; + break; + case CutomDataComponent.CustomData1X: + bit = CustomData1XBit; + break; + case CutomDataComponent.CustomData1Y: + bit = CustomData1YBit; + break; + case CutomDataComponent.CustomData1Z: + bit = CustomData1ZBit; + break; + case CutomDataComponent.CustomData1W: + bit = CustomData1WBit; + break; + case CutomDataComponent.CustomData2X: + bit = CustomData2XBit; + break; + case CutomDataComponent.CustomData2Y: + bit = CustomData2YBit; + break; + case CutomDataComponent.CustomData2Z: + bit = CustomData2ZBit; + break; + case CutomDataComponent.CustomData2W: + bit = CustomData2WBit; + break; + } + + bit = bit << dataBitPos; + int clearBit = ~(15 << dataBitPos); //~ (1111 << dataBitPos) + + int materialBit = material.GetInteger(GetCustomDataFlagID(dataIndex)); + materialBit = materialBit & clearBit; + materialBit = materialBit | bit; + material.SetInteger(GetCustomDataFlagID(dataIndex), materialBit); + } + + public bool IsCustomDataOn() + { + int prop0Flag = material.GetInteger(CustomDataFlag0Id); + int prop1Flag = material.GetInteger(CustomDataFlag1Id); + int prop2Flag = material.GetInteger(CustomDataFlag2Id); + int prop3Flag = material.GetInteger(CustomDataFlag3Id); + uint dataOnBit = 0b_1000_1000_1000_1000_1000_1000_1000_1000; //10001000100010001000100010001000; + + return ((prop0Flag & dataOnBit) > 0) || ((prop1Flag & dataOnBit) > 0) || ((prop2Flag & dataOnBit) > 0) || + ((prop3Flag & dataOnBit) > 0); + } + + bool CheckCustomData(int dataIndex, int flagIndex) + { + int flagID = 0; + switch (flagIndex) + { + case 0: + flagID = CustomDataFlag0Id; + break; + case 1: + flagID = CustomDataFlag1Id; + break; + case 2: + flagID = CustomDataFlag2Id; + break; + case 3: + flagID = CustomDataFlag3Id; + break; + } + + int flag = material.GetInteger(flagID); + int i = 0; + while (i < 8) + { + int bit = flag >> (4 * i); + if (dataIndex == 1) + { + if ((bit & 0b_1000) > 0 && (bit & 0b_0100) > 0) + { + return true; + } + } + else if (dataIndex == 2) + { + if ((bit & 0b_1000) > 0 && (bit & 0b_0100) == 0) + { + return true; + } + } + + i += 1; + } + + return false; + } + + public bool IsCustomData1On() + { + if (!IsCustomDataOn()) + { + return false; + } + + bool isCustomData1On = false; + isCustomData1On |= CheckCustomData(1, 0); + isCustomData1On |= CheckCustomData(1, 1); + isCustomData1On |= CheckCustomData(1, 2); + isCustomData1On |= CheckCustomData(1, 3); + return isCustomData1On; + } + + public bool IsCustomData2On() + { + if (!IsCustomDataOn()) + { + return false; + } + + bool isCustomData1On = false; + isCustomData1On |= CheckCustomData(2, 0); + isCustomData1On |= CheckCustomData(2, 1); + isCustomData1On |= CheckCustomData(2, 2); + isCustomData1On |= CheckCustomData(2, 3); + return isCustomData1On; + + } + + #endregion + + public const string UVModeFlag0Name = "_UVModeFlag0"; + public const string UVModeFlagType0Name = "_UVModeFlagType0"; + public static int UVModeFlag0PropID = Shader.PropertyToID(UVModeFlag0Name); + public static int UVModeFlagType0PropID = Shader.PropertyToID(UVModeFlagType0Name); + + public string GetUVModePropName(int dataIndex) + { + switch (dataIndex) + { + case 0: + return UVModeFlag0Name; + } + + return null; + } + + public enum UVMode + { + DefaultUVChannel, //0 0b_00 modeIndex 00 + SpecialUVChannel, //1 0b_01 modeIndex 00 + PolarOrTwirl, //2 0b_10 modeIndex 00 + Cylinder, //3 0b_11 modeIndex 00 + MainTex, //0 0b_00 modeIndex 01 + ScreenUV, //1 0b_01 modeIndex 01 + WorldPos, //2 0b_10 modeIndex 01 + ObjectPos, //3 0b_11 modeIndex 01 + CommonUV, //0 0b_00 modeIndex 10 + UnknownOrMixed = -1 + } + + public const int FLAG_BIT_UVMODE_POS_0_MAINTEX = 0 * 2; + public const int FLAG_BIT_UVMODE_POS_0_MASKMAP = 1 * 2; + public const int FLAG_BIT_UVMODE_POS_0_MASKMAP_2 = 2 * 2; + public const int FLAG_BIT_UVMODE_POS_0_MASKMAP_3 = 3 * 2; + public const int FLAG_BIT_UVMODE_POS_0_NOISE_MAP = 4 * 2; + public const int FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP = 5 * 2; + public const int FLAG_BIT_UVMODE_POS_0_EMISSION_MAP = 6 * 2; + public const int FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP = 7 * 2; + public const int FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP = 8 * 2; + public const int FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP = 9 * 2; + public const int FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP = 10 * 2; + public const int FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP = 11 * 2; + public const int FLAG_BIT_UVMODE_POS_0_BUMPMAP = 12 * 2; + public const int FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP = 13 * 2; + public const int FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE = 14 * 2; + public const int FLAG_BIT_UVMODE_POS_0_SHAREDUV = 15 * 2; + + public void GetUVModeFlagPropID(int flagIndex, out int flagID, out int flagTypeID) + { + switch (flagIndex) + { + case 0: + flagID = UVModeFlag0PropID; + flagTypeID = UVModeFlagType0PropID; + return; + } + + flagID = 0; + flagTypeID = 0; + + } + + public void SetUVMode(UVMode mode, int uvModePos, int flagIndex = 0) + { + GetUVModeFlagPropID(flagIndex, out int uvModeFlagPropId, out int uvModeFlagTypePropId); + int uvModeFlag = material.GetInteger(uvModeFlagPropId); + int uvModeFlagType = material.GetInteger(uvModeFlagTypePropId); + + + int clearFlag = 0b_11 << uvModePos; + clearFlag = ~ clearFlag; + + uvModeFlag &= clearFlag; + int modeBit = (int)mode % 4 << uvModePos; + uvModeFlag |= modeBit; + uvModeFlagType &= clearFlag; + int typeBit = (int)mode / 4 << uvModePos; + uvModeFlagType |= typeBit; + + material.SetInteger(uvModeFlagPropId, uvModeFlag); + material.SetInteger(uvModeFlagTypePropId, uvModeFlagType); + } + + public UVMode GetUVMode(int uvModePos, int flagIndex = 0) + { + GetUVModeFlagPropID(flagIndex, out int uvModeFlagPropId, out int uvModeFlagTypePropId); + int uvModeFlag = material.GetInteger(uvModeFlagPropId); + uvModeFlag = uvModeFlag >> uvModePos; + uvModeFlag &= 0b_11; + int uvModeFlagType = material.GetInteger(uvModeFlagTypePropId); + uvModeFlagType = uvModeFlagType >> uvModePos; + uvModeFlagType &= 0b_11; + return (UVMode)(uvModeFlag + 4 * uvModeFlagType); + } + + public bool CheckIsUVModeOn(UVMode mode) + { + uint uvModeFlag0 = (uint)material.GetInteger(UVModeFlag0PropID); + uint uvModeFlagType0 = (uint)material.GetInteger(UVModeFlagType0PropID); + + uint uvModeflagBit = (uint)mode % 4; + uint uvModeflagTypeBit = (uint)mode / 4; + + bool isUvMode = false; + for (int i = 0; i < 16; i++) + { + uint checkflagBit = uvModeFlag0 >> (i * 2); + checkflagBit = checkflagBit & 0b_11; + uint checkflagTypeBit = uvModeflagTypeBit >> (i * 2); + checkflagTypeBit = checkflagTypeBit & 0b_11; + if (checkflagBit == uvModeflagBit && checkflagTypeBit == uvModeflagTypeBit) + { + isUvMode = true; + break; + } + } + + return isUvMode; + } + + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA = 0 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1 = 1 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2 = 2 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3 = 3 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK = 4 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP = 5 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP = 6 * 2; + public const int FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP = 7 * 2; + + + public enum ColorChannel + { + X, + Y, + Z, + W, + UnKnownOrMixedValue + } + + public void SetColorChanel(ColorChannel channel, int colorChannelFlagPos) + { + int colorChannelFlag = material.GetInteger(colorChannelFlagId); + + int clearFlag = 0b_11 << colorChannelFlagPos; + clearFlag = ~ clearFlag; + + colorChannelFlag &= clearFlag; + int channelBit = (int)channel << colorChannelFlagPos; + colorChannelFlag |= channelBit; + + material.SetInteger(colorChannelFlagId, colorChannelFlag); + } + + public ColorChannel GetColorChanel(int colorChannelFlagPos) + { + int colorChannelFlag = material.GetInteger(colorChannelFlagId); + colorChannelFlag = colorChannelFlag >> colorChannelFlagPos; + colorChannelFlag &= 0b_11; + return (ColorChannel)colorChannelFlag; + } + + public const int FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND = 0 * 3; + public const int FLAG_BIT_PNOISE_BLEND_POS_0_MASK = 1 * 3; + public const int FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE = 2 * 3; + public const int FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT = 3 * 3; + public const int FLAG_BIT_PNOISE_BLEND_POS_0_MAINTEX = 4 * 3; + + public enum PNoiseBlendMode + { + NotUse = 0, + Multiply = 1, + Min = 2, + HardLight = 3, + UnKnownOrMixedValue = -1 + + //后续看看要不要更多吧 + } + + public void SetPNoiseBlendMode(PNoiseBlendMode mode, int pNoiseBlendModeFlagPos) + { + int pNoiseBlendFlag = material.GetInteger(pNoiseBlendFlagId); + int blendMode = (int)mode; + if (blendMode < 0) return; + int clearFlag = 0b_111 << pNoiseBlendModeFlagPos; + clearFlag = ~clearFlag; + pNoiseBlendFlag &= clearFlag; + int pNoiseBlendBit = blendMode << pNoiseBlendModeFlagPos; + //先不考虑超过4个选项(2bit)的情况 + pNoiseBlendFlag |= pNoiseBlendBit; + material.SetInteger(pNoiseBlendFlagId, pNoiseBlendFlag); + } + + public PNoiseBlendMode GetPNoiseBlendMode(int pNoiseBlendModeFlagPos) + { + int pNoiseBlendFlag = material.GetInteger(pNoiseBlendFlagId); + pNoiseBlendFlag = pNoiseBlendFlag >> pNoiseBlendModeFlagPos; + pNoiseBlendFlag &= 0b_111; + //先不考虑超过4个选项(2bit)的情况 + return (PNoiseBlendMode)pNoiseBlendFlag; + } + + } +} diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderFlags.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFlags.cs.meta new file mode 100644 index 00000000..6882a953 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b35030d15614953b769ad23d9fe5dfe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentProtocol.cs b/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentProtocol.cs new file mode 100644 index 00000000..4db4992d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentProtocol.cs @@ -0,0 +1,36 @@ +namespace NBShader +{ + /// + /// Serialized material mode values used by NBShader intent resolution. + /// These values mirror shader properties and must remain compatible with existing materials. + /// + internal static class NBShaderMaterialIntentProtocol + { + public const int MeshSourceParticle = 0; + public const int MeshSourceUIEffectRawImage = 2; + public const int MeshSourceUIEffectSprite = 3; + public const int MeshSourceUIEffectBaseMap = 4; + public const int MeshSourceUIParticle = 5; + + public const int TransparentOpaque = 0; + public const int TransparentTransparent = 1; + public const int TransparentCutOff = 2; + + public const int FxLightUnlit = 0; + public const int FxLightBlinnPhong = 1; + public const int FxLightHalfLambert = 2; + public const int FxLightPbr = 3; + public const int FxLightSixWay = 4; + + public const int BlendAlpha = 0; + public const int BlendPremultiply = 1; + public const int BlendAdditive = 2; + public const int BlendMultiply = 3; + public const int BlendOpaque = 4; + + public const int TimeUnscaled = 1; + public const int TimeScriptable = 2; + + public const int VatTyflow = 1; + } +} diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentProtocol.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentProtocol.cs.meta new file mode 100644 index 00000000..2720ed3f --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentProtocol.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c88a6a4a7ec940c4aa97cfdcf4a8349e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentResolver.cs b/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentResolver.cs new file mode 100644 index 00000000..02fce045 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentResolver.cs @@ -0,0 +1,574 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace NBShader +{ + /// + /// Resolves the serialized material feature intent into tier-filtered keywords and pass requirements. + /// This class is read-only: it never changes material properties, keywords, or shader pass state. + /// + internal static class NBShaderMaterialIntentResolver + { + private static readonly KeywordToggleBinding[] ToggleKeywordBindings = + { + new KeywordToggleBinding("_SoftParticlesEnabled", "_SOFTPARTICLES_ON"), + new KeywordToggleBinding("_DistanceFade_Toggle", "_DISTANCE_FADE"), + new KeywordToggleBinding("_StencilWithoutPlayerToggle", "_STENCIL_WITHOUT_PLAYER"), + new KeywordToggleBinding("_Mask_Toggle", "_MASKMAP_ON"), + new KeywordToggleBinding("_noisemapEnabled", "_NOISEMAP"), + new KeywordToggleBinding("_EmissionEnabled", "_EMISSION"), + new KeywordToggleBinding("_ColorBlendMap_Toggle", "_COLORMAPBLEND"), + new KeywordToggleBinding("_RampColorToggle", "_COLOR_RAMP"), + new KeywordToggleBinding("_Dissolve_Toggle", "_DISSOLVE"), + new KeywordToggleBinding("_ProgramNoise_Toggle", "_PROGRAM_NOISE"), + new KeywordToggleBinding("_SharedUVToggle", "_SHARED_UV"), + new KeywordToggleBinding("_fresnelEnabled", "_FRESNEL"), + new KeywordToggleBinding("_ParallaxMapping_Toggle", "_PARALLAX_MAPPING"), + new KeywordToggleBinding("_VertexOffset_Toggle", "_VERTEX_OFFSET"), + new KeywordToggleBinding("_FlipbookBlending", "_FLIPBOOKBLENDING_ON"), + new KeywordToggleBinding("_BumpMapToggle", "_NORMALMAP"), + new KeywordToggleBinding("_MatCapToggle", "_MATCAP"), + new KeywordToggleBinding("_BlinnPhongSpecularToggle", "_SPECULAR_COLOR"), + new KeywordToggleBinding("_SixWayColorAbsorptionToggle", "VFX_SIX_WAY_ABSORPTION"), + new KeywordToggleBinding("_DepthDecal_Toggle", "_DEPTH_DECAL"), + new KeywordToggleBinding("_DepthOutline_Toggle", "_DEPTH_OUTLINE"), + new KeywordToggleBinding("_OverrideZ_Toggle", "_OVERRIDE_Z"), + new KeywordToggleBinding("_Mask2_Toggle", "_MASKMAP2_ON"), + new KeywordToggleBinding("_Mask3_Toggle", "_MASKMAP3_ON"), + new KeywordToggleBinding("_noiseMaskMap_Toggle", "_NOISE_MASKMAP"), + new KeywordToggleBinding("_Distortion_Choraticaberrat_Toggle", "_CHROMATIC_ABERRATION"), + new KeywordToggleBinding("_DissolveMask_Toggle", "_DISSOLVE_MASK"), + new KeywordToggleBinding("_Dissolve_useRampMap_Toggle", "_DISSOLVE_RAMP"), + new KeywordToggleBinding("_ProgramNoise_Simple_Toggle", "_PROGRAM_NOISE_SIMPLE"), + new KeywordToggleBinding("_ProgramNoise_Voronoi_Toggle", "_PROGRAM_NOISE_VORONOI"), + new KeywordToggleBinding("_VertexOffset_Mask_Toggle", "_VERTEX_OFFSET_MASKMAP"), + new KeywordToggleBinding("_NB_Debug_Dissolve", "NB_DEBUG_DISSOLVE"), + new KeywordToggleBinding("_NB_Debug_Distort", "NB_DEBUG_DISTORT"), + new KeywordToggleBinding("_NB_Debug_Fresnel", "NB_DEBUG_FRESNEL"), + new KeywordToggleBinding("_NB_Debug_Mask", "NB_DEBUG_MASK"), + new KeywordToggleBinding("_NB_Debug_PNoise", "NB_DEBUG_PNOISE"), + new KeywordToggleBinding("_NB_Debug_VertexOffset", "NB_DEBUG_VERTEX_OFFSET") + }; + + private static readonly string[] HoudiniVatKeywords = + { + "_HOUDINI_VAT_SOFTBODY", + "_HOUDINI_VAT_RIGIDBODY", + "_HOUDINI_VAT_DYNAMIC_REMESH", + "_HOUDINI_VAT_PARTICLE_SPRITE" + }; + + private static readonly string[] TyflowVatKeywords = + { + "_TYFLOW_VAT_ABSOLUTE", + "_TYFLOW_VAT_RELATIVE", + "_TYFLOW_VAT_SKIN_R", + "_TYFLOW_VAT_SKIN_PR", + "_TYFLOW_VAT_SKIN_PRSAVE", + "_TYFLOW_VAT_SKIN_PRSXYZ" + }; + + public static bool IsNBShaderMaterial(Material material) + { + return material != null && + material.shader != null && + material.shader.name == NBShaderFeatureCatalog.ShaderName; + } + + public static NBShaderMaterialIntentResult Resolve(Material material, NBShaderFeatureTier tier) + { + return Resolve( + material, + tier, + NBShaderFeatureCatalog.RawKeywords, + NBShaderPassFeatureCatalog.GetDefaultAllowedPassFeatures(tier)); + } + + public static NBShaderMaterialIntentResult Resolve( + Material material, + NBShaderFeatureTier tier, + IEnumerable allowedManagedKeywords, + IEnumerable allowedPassFeatureIds) + { + var allowedKeywords = BuildAllowedKeywordSet(allowedManagedKeywords); + var allowedPassFeatures = BuildAllowedPassFeatureSet(allowedPassFeatureIds); + var intendedKeywords = ResolveIntendedManagedKeywords(material); + var effectiveKeywords = FilterAllowedKeywords(intendedKeywords, allowedKeywords); + ApplyKeywordDependencies(effectiveKeywords); + var strippedKeywords = BuildDifference(intendedKeywords, effectiveKeywords); + var passIntents = ResolvePassIntents(material, effectiveKeywords, allowedPassFeatures); + + return new NBShaderMaterialIntentResult( + material, + tier, + ToCatalogOrderedArray(intendedKeywords), + ToCatalogOrderedArray(effectiveKeywords), + ToCatalogOrderedArray(strippedKeywords), + passIntents); + } + + private static HashSet ResolveIntendedManagedKeywords(Material material) + { + var keywords = new HashSet(StringComparer.Ordinal); + if (!IsNBShaderMaterial(material)) + return keywords; + + for (var i = 0; i < ToggleKeywordBindings.Length; i++) + { + var binding = ToggleKeywordBindings[i]; + if (GetFloat(material, binding.propertyName, 0f) > 0.5f) + AddManagedKeyword(keywords, binding.keyword); + } + + int meshMode = GetInt(material, "_MeshSourceMode", 0); + int transparentMode = GetInt(material, "_TransparentMode", NBShaderMaterialIntentProtocol.TransparentTransparent); + if (transparentMode == NBShaderMaterialIntentProtocol.TransparentCutOff) + AddManagedKeyword(keywords, "_ALPHATEST_ON"); + + int blendMode = ResolveBlendMode(material, transparentMode); + switch (blendMode) + { + case NBShaderMaterialIntentProtocol.BlendPremultiply: + case NBShaderMaterialIntentProtocol.BlendAdditive: + AddManagedKeyword(keywords, "_ALPHAPREMULTIPLY_ON"); + break; + case NBShaderMaterialIntentProtocol.BlendMultiply: + AddManagedKeyword(keywords, "_ALPHAMODULATE_ON"); + break; + } + + if (IsParticleMeshSource(meshMode)) + AddManagedKeyword(keywords, "_PARCUSTOMDATA_ON"); + + switch (GetInt(material, "_TimeMode", 0)) + { + case NBShaderMaterialIntentProtocol.TimeUnscaled: + AddManagedKeyword(keywords, "_UNSCALETIME"); + break; + case NBShaderMaterialIntentProtocol.TimeScriptable: + AddManagedKeyword(keywords, "_SCRIPTABLETIME"); + break; + } + + switch (GetInt(material, "_FxLightMode", NBShaderMaterialIntentProtocol.FxLightUnlit)) + { + case NBShaderMaterialIntentProtocol.FxLightUnlit: + AddManagedKeyword(keywords, "_FX_LIGHT_MODE_UNLIT"); + break; + case NBShaderMaterialIntentProtocol.FxLightBlinnPhong: + AddManagedKeyword(keywords, "_FX_LIGHT_MODE_BLINN_PHONG"); + break; + case NBShaderMaterialIntentProtocol.FxLightHalfLambert: + AddManagedKeyword(keywords, "_FX_LIGHT_MODE_HALF_LAMBERT"); + break; + case NBShaderMaterialIntentProtocol.FxLightPbr: + AddManagedKeyword(keywords, "_FX_LIGHT_MODE_PBR"); + break; + case NBShaderMaterialIntentProtocol.FxLightSixWay: + AddManagedKeyword(keywords, "_FX_LIGHT_MODE_SIX_WAY"); + break; + } + + if (GetInt(material, "_DistortMode", 0) == 1) + AddManagedKeyword(keywords, "_DISTORT_REFRACTION"); + + if (GetInt(material, "_RampColorSourceMode", 0) == 1) + AddManagedKeyword(keywords, "_COLOR_RAMP_MAP"); + + if (GetInt(material, "_DissolveRampSourceMode", 0) == 1 && + GetFloat(material, "_Dissolve_useRampMap_Toggle", 0f) > 0.5f) + { + AddManagedKeyword(keywords, "_DISSOLVE_RAMP_MAP"); + } + + if (!IsUIEffectMeshSource(meshMode) && GetInt(material, "_ScreenDistortModeToggle", 0) != 0) + AddManagedKeyword(keywords, "_SCREEN_DISTORT_MODE"); + + ResolveVatKeywords(material, keywords); + + return keywords; + } + + private static void ResolveVatKeywords(Material material, HashSet keywords) + { + if (GetFloat(material, "_VAT_Toggle", 0f) <= 0.5f) + return; + + keywords.Remove("_FLIPBOOKBLENDING_ON"); + AddManagedKeyword(keywords, "_VAT"); + + if (GetInt(material, "_VATMode", 0) == NBShaderMaterialIntentProtocol.VatTyflow) + { + AddManagedKeyword(keywords, "_VAT_TYFLOW"); + AddIndexedKeyword(keywords, TyflowVatKeywords, GetInt(material, "_TyFlowVATSubMode", 0)); + } + else + { + AddManagedKeyword(keywords, "_VAT_HOUDINI"); + AddIndexedKeyword(keywords, HoudiniVatKeywords, GetInt(material, "_HoudiniVATSubMode", 0)); + } + } + + private static NBShaderPassIntent[] ResolvePassIntents( + Material material, + HashSet effectiveKeywords, + HashSet allowedPassFeatures) + { + var result = new List(7); + bool isNBShaderMaterial = IsNBShaderMaterial(material); + int meshMode = GetInt(material, "_MeshSourceMode", 0); + int transparentMode = GetInt(material, "_TransparentMode", NBShaderMaterialIntentProtocol.TransparentTransparent); + bool uiEffect = IsUIEffectMeshSource(meshMode); + int screenDistortMode = isNBShaderMaterial ? GetInt(material, "_ScreenDistortModeToggle", 0) : 0; + bool screenDistortKeywordEnabled = effectiveKeywords.Contains("_SCREEN_DISTORT_MODE"); + bool screenDistortEnabled = !uiEffect && screenDistortMode != 0 && screenDistortKeywordEnabled; + bool disableMainPass = GetFloat(material, "_DisableMainPassToggle", 0f) > 0.5f; + bool mainPassEnabled = isNBShaderMaterial && (!screenDistortEnabled || !disableMainPass); + + result.Add(NBShaderPassIntent.CreateCore( + NBShaderPassFeatureCatalog.MainForwardPassName, + mainPassEnabled, + mainPassEnabled ? "main pass" : "disabled by screen distort material intent")); + + AddManagedPass( + result, + NBShaderPassFeatureCatalog.BackFirstPassId, + !uiEffect && + transparentMode == NBShaderMaterialIntentProtocol.TransparentTransparent && + GetFloat(material, "_BackFirstPassToggle", 0f) > 0.5f, + allowedPassFeatures, + "back first material toggle"); + + AddManagedPass( + result, + NBShaderPassFeatureCatalog.CameraOpaqueDistortPassId, + screenDistortEnabled && screenDistortMode == 2, + allowedPassFeatures, + "camera opaque screen distort material mode"); + + AddManagedPass( + result, + NBShaderPassFeatureCatalog.DeferredDistortPassId, + screenDistortEnabled && screenDistortMode == 1, + allowedPassFeatures, + "deferred screen distort material mode"); + + AddManagedPass( + result, + NBShaderPassFeatureCatalog.DepthOnlyPassId, + !uiEffect && ResolveZWrite(material, transparentMode), + allowedPassFeatures, + "depth write material state"); + + AddManagedPass( + result, + NBShaderPassFeatureCatalog.ShadowCasterPassId, + !uiEffect && + GetFloat(material, "_AffectsShadows", 0f) > 0.5f && + IsKnownTransparentMode(GetInt(material, "_TransparentMode", NBShaderMaterialIntentProtocol.TransparentTransparent)), + allowedPassFeatures, + "shadow material state"); + + AddManagedPass( + result, + NBShaderPassFeatureCatalog.Universal2DPassId, + isNBShaderMaterial, + allowedPassFeatures, + "URP 2D renderer pass"); + + return result.ToArray(); + } + + private static void AddManagedPass( + List result, + string featureId, + bool enabledByMaterial, + HashSet allowedPassFeatures, + string reason) + { + NBShaderPassFeatureInfo feature; + if (!NBShaderPassFeatureCatalog.TryGetPassFeature(featureId, out feature)) + return; + + bool allowedByTier = allowedPassFeatures == null || allowedPassFeatures.Contains(featureId); + result.Add(new NBShaderPassIntent( + featureId, + feature.passName, + enabledByMaterial, + allowedByTier, + enabledByMaterial && allowedByTier, + reason)); + } + + private static HashSet BuildAllowedKeywordSet(IEnumerable allowedManagedKeywords) + { + var result = new HashSet(StringComparer.Ordinal); + if (allowedManagedKeywords == null) + { + for (var i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++) + result.Add(NBShaderFeatureCatalog.RawKeywords[i]); + return result; + } + + foreach (var keyword in allowedManagedKeywords) + { + if (NBShaderFeatureCatalog.IsManagedKeyword(keyword)) + result.Add(keyword); + } + + return result; + } + + private static HashSet BuildAllowedPassFeatureSet(IEnumerable allowedPassFeatureIds) + { + if (allowedPassFeatureIds == null) + return null; + + var result = new HashSet(StringComparer.Ordinal); + foreach (var featureId in allowedPassFeatureIds) + { + if (NBShaderPassFeatureCatalog.IsManagedPassFeature(featureId)) + result.Add(featureId); + } + + return result; + } + + private static HashSet FilterAllowedKeywords(HashSet source, HashSet allowed) + { + var result = new HashSet(StringComparer.Ordinal); + foreach (var keyword in source) + { + if (allowed.Contains(keyword)) + result.Add(keyword); + } + + return result; + } + + private static void ApplyKeywordDependencies(HashSet keywords) + { + RemoveIfParentMissing(keywords, "_MASKMAP_ON", "_MASKMAP2_ON", "_MASKMAP3_ON", "NB_DEBUG_MASK"); + RemoveIfParentMissing(keywords, "_NOISEMAP", "_NOISE_MASKMAP", "NB_DEBUG_DISTORT", "_SCREEN_DISTORT_MODE", "_DISTORT_REFRACTION"); + RemoveIfParentMissing(keywords, "_COLOR_RAMP", "_COLOR_RAMP_MAP"); + RemoveIfParentMissing(keywords, "_DISSOLVE", "_DISSOLVE_MASK", "_DISSOLVE_RAMP", "NB_DEBUG_DISSOLVE"); + RemoveIfParentMissing(keywords, "_DISSOLVE_RAMP", "_DISSOLVE_RAMP_MAP"); + RemoveIfParentMissing(keywords, "_PROGRAM_NOISE", "_PROGRAM_NOISE_SIMPLE", "_PROGRAM_NOISE_VORONOI", "NB_DEBUG_PNOISE"); + RemoveIfParentMissing(keywords, "_FRESNEL", "NB_DEBUG_FRESNEL"); + RemoveIfParentMissing(keywords, "_VERTEX_OFFSET", "_VERTEX_OFFSET_MASKMAP", "NB_DEBUG_VERTEX_OFFSET"); + RemoveIfParentMissing(keywords, "_VAT", "_VAT_HOUDINI", "_VAT_TYFLOW"); + RemoveIfParentMissing(keywords, "_VAT_HOUDINI", HoudiniVatKeywords); + RemoveIfParentMissing(keywords, "_VAT_TYFLOW", TyflowVatKeywords); + RemoveIfParentMissing(keywords, "_FX_LIGHT_MODE_SIX_WAY", "VFX_SIX_WAY_ABSORPTION"); + } + + private static void RemoveIfParentMissing(HashSet keywords, string parentKeyword, params string[] dependentKeywords) + { + if (keywords.Contains(parentKeyword) || dependentKeywords == null) + return; + + for (var i = 0; i < dependentKeywords.Length; i++) + keywords.Remove(dependentKeywords[i]); + } + + private static HashSet BuildDifference(HashSet source, HashSet retained) + { + var result = new HashSet(StringComparer.Ordinal); + foreach (var keyword in source) + { + if (!retained.Contains(keyword)) + result.Add(keyword); + } + + return result; + } + + private static void AddManagedKeyword(HashSet keywords, string keyword) + { + if (NBShaderFeatureCatalog.IsManagedKeyword(keyword)) + keywords.Add(keyword); + } + + private static void AddIndexedKeyword(HashSet keywords, string[] source, int index) + { + if (source == null || index < 0 || index >= source.Length) + return; + + AddManagedKeyword(keywords, source[index]); + } + + private static string[] ToCatalogOrderedArray(HashSet keywords) + { + if (keywords == null || keywords.Count == 0) + return new string[0]; + + var result = new List(); + for (var i = 0; i < NBShaderFeatureCatalog.RawKeywords.Length; i++) + { + var keyword = NBShaderFeatureCatalog.RawKeywords[i]; + if (keywords.Contains(keyword)) + result.Add(keyword); + } + + return result.ToArray(); + } + + private static bool IsParticleMeshSource(int mode) + { + return mode == NBShaderMaterialIntentProtocol.MeshSourceParticle || + mode == NBShaderMaterialIntentProtocol.MeshSourceUIParticle; + } + + private static bool IsUIEffectMeshSource(int mode) + { + return mode == NBShaderMaterialIntentProtocol.MeshSourceUIEffectRawImage || + mode == NBShaderMaterialIntentProtocol.MeshSourceUIEffectSprite || + mode == NBShaderMaterialIntentProtocol.MeshSourceUIEffectBaseMap || + mode == NBShaderMaterialIntentProtocol.MeshSourceUIParticle; + } + + private static bool IsKnownTransparentMode(int mode) + { + return mode == NBShaderMaterialIntentProtocol.TransparentOpaque || + mode == NBShaderMaterialIntentProtocol.TransparentTransparent || + mode == NBShaderMaterialIntentProtocol.TransparentCutOff; + } + + private static int ResolveBlendMode(Material material, int transparentMode) + { + if (!IsKnownTransparentMode(transparentMode)) + return GetInt(material, "_Blend", 0); + + if (transparentMode == NBShaderMaterialIntentProtocol.TransparentOpaque || + transparentMode == NBShaderMaterialIntentProtocol.TransparentCutOff) + return NBShaderMaterialIntentProtocol.BlendOpaque; + + int blendMode = GetInt(material, "_Blend", 0); + return blendMode == NBShaderMaterialIntentProtocol.BlendOpaque + ? NBShaderMaterialIntentProtocol.BlendAlpha + : blendMode; + } + + private static bool ResolveZWrite(Material material, int transparentMode) + { + bool zWrite; + if (transparentMode == NBShaderMaterialIntentProtocol.TransparentOpaque || + transparentMode == NBShaderMaterialIntentProtocol.TransparentCutOff) + { + zWrite = true; + } + else if (transparentMode == NBShaderMaterialIntentProtocol.TransparentTransparent) + { + zWrite = false; + } + else + { + zWrite = GetInt(material, "_ZWrite", 0) == 1; + } + + float forceZWrite = GetFloat(material, "_ForceZWriteToggle", 0f); + if (forceZWrite > 0.5f && forceZWrite < 1.5f) + return true; + if (forceZWrite > 1.5f) + return false; + return zWrite; + } + + private static float GetFloat(Material material, string propertyName, float fallback) + { + return material != null && material.HasProperty(propertyName) ? material.GetFloat(propertyName) : fallback; + } + + private static int GetInt(Material material, string propertyName, int fallback) + { + return Mathf.RoundToInt(GetFloat(material, propertyName, fallback)); + } + + private struct KeywordToggleBinding + { + public readonly string propertyName; + public readonly string keyword; + + public KeywordToggleBinding(string propertyName, string keyword) + { + this.propertyName = propertyName; + this.keyword = keyword; + } + } + } + + internal sealed class NBShaderMaterialIntentResult + { + public readonly Material material; + public readonly NBShaderFeatureTier tier; + public readonly string[] intendedManagedKeywords; + public readonly string[] effectiveKeywords; + public readonly string[] strippedManagedKeywords; + public readonly NBShaderPassIntent[] passes; + public readonly string[] includedPassNames; + public readonly string[] strippedPassNames; + + public NBShaderMaterialIntentResult( + Material material, + NBShaderFeatureTier tier, + string[] intendedManagedKeywords, + string[] effectiveKeywords, + string[] strippedManagedKeywords, + NBShaderPassIntent[] passes) + { + this.material = material; + this.tier = tier; + this.intendedManagedKeywords = intendedManagedKeywords ?? new string[0]; + this.effectiveKeywords = effectiveKeywords ?? new string[0]; + this.strippedManagedKeywords = strippedManagedKeywords ?? new string[0]; + this.passes = passes ?? new NBShaderPassIntent[0]; + includedPassNames = BuildPassNameArray(this.passes, true); + strippedPassNames = BuildPassNameArray(this.passes, false); + } + + private static string[] BuildPassNameArray(NBShaderPassIntent[] passes, bool included) + { + var result = new List(); + for (var i = 0; i < passes.Length; i++) + { + var pass = passes[i]; + if (pass.included == included && !string.IsNullOrEmpty(pass.passName)) + result.Add(pass.passName); + } + + return result.ToArray(); + } + } + + internal sealed class NBShaderPassIntent + { + public readonly string featureId; + public readonly string passName; + public readonly bool enabledByMaterial; + public readonly bool allowedByTier; + public readonly bool included; + public readonly string reason; + + public NBShaderPassIntent( + string featureId, + string passName, + bool enabledByMaterial, + bool allowedByTier, + bool included, + string reason) + { + this.featureId = featureId; + this.passName = passName; + this.enabledByMaterial = enabledByMaterial; + this.allowedByTier = allowedByTier; + this.included = included; + this.reason = reason; + } + + public static NBShaderPassIntent CreateCore(string passName, bool included, string reason) + { + return new NBShaderPassIntent(null, passName, included, true, included, reason); + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentResolver.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentResolver.cs.meta new file mode 100644 index 00000000..1883b145 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderMaterialIntentResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6fbac1987464c5f9bf46b3b121d4c21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderPassFeatureCatalog.cs b/Packages/NB_FX/NBShaders2/Runtime/NBShaderPassFeatureCatalog.cs new file mode 100644 index 00000000..16c3db62 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderPassFeatureCatalog.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; + +namespace NBShader +{ + /// + /// Catalog of NBShader passes that can be controlled by feature tiering. + /// UniversalForward is the primary pass and is intentionally not listed as a tier feature. + /// + internal static class NBShaderPassFeatureCatalog + { + public const string MainForwardPassName = "UniversalForward"; + + public const string BackFirstPassId = "pass.backFirst"; + public const string CameraOpaqueDistortPassId = "pass.screenDistort.cameraOpaque"; + public const string DeferredDistortPassId = "pass.screenDistort.deferred"; + public const string DepthOnlyPassId = "pass.depthOnly"; + public const string ShadowCasterPassId = "pass.shadowCaster"; + public const string Universal2DPassId = "pass.universal2D"; + + public static readonly NBShaderPassFeatureInfo[] RawPassFeatures = + { + new NBShaderPassFeatureInfo(BackFirstPassId, "SRPDefaultUnlit", "Back First Pass"), + new NBShaderPassFeatureInfo(CameraOpaqueDistortPassId, "NBCameraOpaqueDistortPass", "Camera Opaque Distort Pass"), + new NBShaderPassFeatureInfo(DeferredDistortPassId, "NBDeferredDistortPass", "Deferred Distort Pass"), + new NBShaderPassFeatureInfo(DepthOnlyPassId, "DepthOnly", "Depth Only Pass"), + new NBShaderPassFeatureInfo(ShadowCasterPassId, "ShadowCaster", "Shadow Caster Pass"), + new NBShaderPassFeatureInfo(Universal2DPassId, "Universal2D", "Universal 2D Pass") + }; + + public static readonly string[] RawPassFeatureIds = BuildRawPassFeatureIds(); + + private static readonly HashSet RawPassFeatureIdSet = new HashSet(RawPassFeatureIds); + private static readonly Dictionary PassFeaturesById = BuildPassFeaturesById(); + private static readonly Dictionary PassFeaturesByPassName = BuildPassFeaturesByPassName(); + + public static bool IsManagedPassFeature(string featureId) + { + return !string.IsNullOrEmpty(featureId) && RawPassFeatureIdSet.Contains(featureId); + } + + public static bool TryGetPassFeature(string featureId, out NBShaderPassFeatureInfo feature) + { + if (string.IsNullOrEmpty(featureId)) + { + feature = null; + return false; + } + + return PassFeaturesById.TryGetValue(featureId, out feature); + } + + public static bool TryGetPassFeatureByPassName(string passName, out NBShaderPassFeatureInfo feature) + { + if (string.IsNullOrEmpty(passName)) + { + feature = null; + return false; + } + + return PassFeaturesByPassName.TryGetValue(passName, out feature); + } + + public static string[] GetDefaultAllowedPassFeatures(NBShaderFeatureTier tier) + { + return (string[])RawPassFeatureIds.Clone(); + } + + private static string[] BuildRawPassFeatureIds() + { + var result = new string[RawPassFeatures.Length]; + for (var i = 0; i < RawPassFeatures.Length; i++) + result[i] = RawPassFeatures[i].id; + return result; + } + + private static Dictionary BuildPassFeaturesById() + { + var result = new Dictionary(); + for (var i = 0; i < RawPassFeatures.Length; i++) + result[RawPassFeatures[i].id] = RawPassFeatures[i]; + return result; + } + + private static Dictionary BuildPassFeaturesByPassName() + { + var result = new Dictionary(); + for (var i = 0; i < RawPassFeatures.Length; i++) + result[RawPassFeatures[i].passName] = RawPassFeatures[i]; + return result; + } + } + + internal sealed class NBShaderPassFeatureInfo + { + public readonly string id; + public readonly string passName; + public readonly string displayName; + + public NBShaderPassFeatureInfo(string id, string passName, string displayName) + { + this.id = id; + this.passName = passName; + this.displayName = displayName; + } + } +} diff --git a/Packages/NB_FX/NBShaders2/Runtime/NBShaderPassFeatureCatalog.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/NBShaderPassFeatureCatalog.cs.meta new file mode 100644 index 00000000..2e766d4d --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/NBShaderPassFeatureCatalog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3238bc94e7aff1147a510c286ad0a673 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/Properties.meta b/Packages/NB_FX/NBShaders2/Runtime/Properties.meta new file mode 100644 index 00000000..f56ad350 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/Properties.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a81bdbda432342429bd339932aee1d15 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/Properties/AssemblyInfo.cs b/Packages/NB_FX/NBShaders2/Runtime/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..6292e5cb --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("com.xuanxuan.nb.shaders2.Editor")] diff --git a/Packages/NB_FX/NBShaders2/Runtime/Properties/AssemblyInfo.cs.meta b/Packages/NB_FX/NBShaders2/Runtime/Properties/AssemblyInfo.cs.meta new file mode 100644 index 00000000..d7bee30f --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f4991907da0943fe9b83896151ba7d2b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Runtime/com.xuanxuan.nb.shaders2.asmdef b/Packages/NB_FX/NBShaders2/Runtime/com.xuanxuan.nb.shaders2.asmdef new file mode 100644 index 00000000..02241a20 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/com.xuanxuan.nb.shaders2.asmdef @@ -0,0 +1,16 @@ +{ + "name": "com.xuanxuan.nb.shaders2", + "rootNamespace": "", + "references": [ + "GUID:8f9e4d586616f13449cfeb86c5f704c2" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/NB_FX/NBShaders2/Runtime/com.xuanxuan.nb.shaders2.asmdef.meta b/Packages/NB_FX/NBShaders2/Runtime/com.xuanxuan.nb.shaders2.asmdef.meta new file mode 100644 index 00000000..02e4e185 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Runtime/com.xuanxuan.nb.shaders2.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: aed681b6b9e69ff4dbd8d55e012b87ff +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Shader.meta b/Packages/NB_FX/NBShaders2/Shader.meta new file mode 100644 index 00000000..3f8a1a8b --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e09642e7a55f5c42b63bcee4d005692 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL.meta b/Packages/NB_FX/NBShaders2/Shader/HLSL.meta new file mode 100644 index 00000000..90609188 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9d3c0ad8c34d43918d438de3d6436c4c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl new file mode 100644 index 00000000..26bfbd0a --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl @@ -0,0 +1,5 @@ +// NBShader2 shader compiler debug switches. +// This file is intentionally included with #include_with_pragmas. + +#undef NB_SHADER_DEBUG_SYMBOLS +#define NB_SHADER_DEBUG_SYMBOLS 0 diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl.meta b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl.meta new file mode 100644 index 00000000..0a7fb9ed --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d7750d9f790e4369b26f49461830b5ea +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderFlags.hlsl b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderFlags.hlsl new file mode 100644 index 00000000..992e3575 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderFlags.hlsl @@ -0,0 +1,324 @@ +#ifndef NBSHADER_FLAGS +#define NBSHADER_FLAGS + + #define FLAG_BIT_SATURABILITY_ON (1 << 0) + #define FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE (1 << 1) + #define FLAG_BIT_PARTICLE_FRESNEL_FADE_ON (1 << 2) + #define FLAG_BIT_PARTICLE_FRESNEL_COLOR_ON (1 << 3) + #define FLAG_BIT_PARTICLE_USETEXCOORD2 (1 << 4) + // #define FLAG_BIT_PARTICLE_DISTANCEFADE_ON (1 << 5) // Obsolete/reserved: keyword-driven (_DISTANCE_FADE). + // #define FLAG_BIT_PARTICLE_CHORATICABERRAT (1 << 6) // Obsolete/reserved: keyword-driven (_CHROMATIC_ABERRATION). + #define FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON (1 << 7) + #define FLAG_BIT_PARTICLE_POLARCOORDINATES_ON (1 << 8) + #define FLAG_BIT_PARTICLE_UTWIRL_ON (1 << 9) + #define FLAG_BIT_PARTICLE_LINEARTOGAMMA_ON (1 << 10) + // #define FLAG_BIT_PARTICLE_FRESNEL_ON (1 << 11) // Obsolete/reserved: keyword-driven (_FRESNEL). + #define FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON (1 << 12) + #define FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA (1 << 13) + #define FLAG_BIT_PARTICLE_UIEFFECT_ON (1 << 14) + #define FLAG_BIT_PARTICLE_UNSCALETIME_ON (1 << 15) + #define FLAG_BIT_PARTICLE_SCRIPTABLETIME_ON (1 << 16) + #define FLAG_BIT_PARTICLE_CUSTOMDATA1_ON (1 << 17) + #define FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON (1 << 18) + #define FLAG_BIT_HUESHIFT_ON (1 << 19) + #define FLAG_BIT_PARTICLE_CUSTOMDATA2_ON (1 << 20) + #define FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE (1 << 21) + #define FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX (1 << 22) + // #define FLAG_BIT_PARTICLE_RAMP_COLOR_MAP_MODE_ON (1 << 23) // Obsolete/reserved: keyword-driven (_COLOR_RAMP_MAP). + #define FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD (1 << 24) + #define FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE (1 << 25) + // #define FLAG_BIT_PARTICLE_DISSOLVE_RAMP_MAP (1 << 26) // Obsolete/reserved: keyword-driven (_DISSOLVE_RAMP_MAP). + // #define FLAG_BIT_PARTICLE_DISSOLVE_MASK (1 << 27) // Obsolete/reserved: keyword-driven (_DISSOLVE_MASK). + #define FLAG_BIT_PARTICLE_BACKCOLOR (1 << 28) + #define FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA (1 << 29) + // #define FLAG_BIT_PARTICLE_VERTEX_OFFSET_ON (1 << 30) // Obsolete/reserved: keyword-driven (_VERTEX_OFFSET). + #define FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR (1 << 31) + // uint _W9ParticleShaderFlags; + + #define FLAG_BIT_PARTICLE_1_TRANSPARENT_MODE (1 << 0) + #define FLAG_BIT_PARTICLE_1_TRANSPARENT_SHADOW_DITHER (1 << 1) + #define FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT (1 << 2) + #define FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT (1 << 3) + #define FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT (1 << 4) + #define FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK (1 << 5) + #define FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY (1 << 6) + #define FLAG_BIT_PARTICLE_1_MASK_REFINE (1 << 7) + #define FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE (1 << 8) + #define FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR (1 << 9) + // #define FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_SIMPLE (1 << 10) // Obsolete/reserved: keyword-driven (_PROGRAM_NOISE_SIMPLE). + // #define FLAG_BIT_PARTICLE_1_DISSOVLE_USE_RAMP (1 << 11) // Obsolete/reserved: keyword-driven (_DISSOLVE_RAMP). + // #define FLAG_BIT_PARTICLE_1_MASK_MAP2 (1 << 12) // Obsolete/reserved: keyword-driven (_MASKMAP2_ON). + // #define FLAG_BIT_PARTICLE_1_MASK_MAP3 (1 << 13) // Obsolete/reserved: keyword-driven (_MASKMAP3_ON). + // #define FLAG_BIT_PARTICLE_1_NOISE_MASKMAP (1 << 14) // Obsolete/reserved: keyword-driven (_NOISE_MASKMAP). + #define FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER (1 << 15) + // #define FLAG_BIT_PARTICLE_1_PROGRAM_NOISE_VORONOI (1 << 16) // Obsolete/reserved: keyword-driven (_PROGRAM_NOISE_VORONOI). + #define FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE (1 << 17) + #define FLAG_BIT_PARTICLE_1_USE_TEXCOORD1 (1 << 18) + #define FLAG_BIT_PARTICLE_1_USE_TEXCOORD2 (1 << 19) + #define FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE (1 << 20) + #define FLAG_BIT_PARTICLE_1_UV_FROM_MESH (1 << 21) + #define FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE (1 << 22) + #define FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM (1 << 23) + #define FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST (1 << 24) + #define FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO (1 << 25) + // #define FLAG_BIT_PARTICLE_1_VERTEXOFFSET_MASKMAP (1 << 26) // Obsolete/reserved: keyword-driven (_VERTEX_OFFSET_MASKMAP). + #define FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE (1 << 27) + #define FLAG_BIT_PARTICLE_1_BUMP_TEX_UV_FOLLOW_MAINTEX (1 << 28) + #define FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP (1 << 29) + #define FLAG_BIT_PARTICLE_1_MATCAP_MULTY_MODE (1 << 30) + + + //WrapMode不能够超过16位(因为会占用x和x+16两个bit位) + #define FLAG_BIT_WRAPMODE_BASEMAP (1 << 0) + #define FLAG_BIT_WRAPMODE_MASKMAP (1 << 1) + #define FLAG_BIT_WRAPMODE_MASKMAP2 (1 << 2) + #define FLAG_BIT_WRAPMODE_NOISEMAP (1 << 3) + #define FLAG_BIT_WRAPMODE_EMISSIONMAP (1 << 4) + #define FLAG_BIT_WRAPMODE_DISSOLVE_MAP (1 << 5) + #define FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP (1 << 6) + #define FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP (1 << 7) + #define FLAG_BIT_WRAPMODE_COLORBLENDMAP (1 << 8) + #define FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP (1 << 9) + #define FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP (1 << 10) + #define FLAG_BIT_WRAPMODE_MASKMAP3 (1 << 11) + #define FLAG_BIT_WRAPMODE_NOISE_MASKMAP (1 << 12) + #define FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP (1 << 13) + #define FLAG_BIT_WRAPMODE_BUMPTEX (1 << 14) + #define FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP (1 << 15) + + #define FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X (0*4) + #define FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y (1*4) + #define FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY (2*4) + #define FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT (3*4) + #define FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X (4*4) + #define FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y (5*4) + #define FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET (6*4) + #define FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY (7*4) + + #define FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X (0*4) + #define FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y (1*4) + #define FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY (2*4) + #define FLAGBIT_POS_1_CUSTOMDATA_SATURATE (3*4) + #define FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X (4*4) + #define FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y (5*4) + #define FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY (6*4) + #define FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY (7*4) + + #define FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X (0*4) + #define FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y (1*4) + #define FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X (2*4) + #define FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y (3*4) + #define FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X (4*4) + #define FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y (5*4) + #define FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST (6*4) + #define FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME (7*4) + + #define FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X (0*4) + #define FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y (1*4) + #define FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X (2*4) + #define FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y (3*4) + #define FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X (4*4) + #define FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y (5*4) + #define FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X (6*4) + #define FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y (7*4) + + #define isCustomDataBit (1 << 3) + #define Data12Bit (1 << 2) + #define DataXYorZWBit (1 << 1) + #define DataXZorYWBit (1 << 0) + + #define FLAG_BIT_UVMODE_POS_0_MAINTEX (0*2) + #define FLAG_BIT_UVMODE_POS_0_MASKMAP (1*2) + #define FLAG_BIT_UVMODE_POS_0_MASKMAP_2 (2*2) + #define FLAG_BIT_UVMODE_POS_0_MASKMAP_3 (3*2) + #define FLAG_BIT_UVMODE_POS_0_NOISE_MAP (4*2) + #define FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP (5*2) + #define FLAG_BIT_UVMODE_POS_0_EMISSION_MAP (6*2) + #define FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP (7*2) + #define FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP (8*2) + #define FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP (9*2) + #define FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP (10*2) + #define FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP (11*2) + #define FLAG_BIT_UVMODE_POS_0_BUMPTEX (12*2) + #define FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP (13*2) + #define FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE (14*2) + #define FLAG_BIT_UVMODE_POS_0_SHAREDUV (15*2) + + #define FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA (0*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1 (1*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2 (2*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3 (3*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK (4*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP (5*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP (6*2) + #define FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP (7*2) + + float GetCustomData(uint flagProperty,int flagPos,float orignValue,half4 cutstomData1,half4 customData2) + { + uint bit = flagProperty >> flagPos; + + // bit &= 15;// binary 1111 这一步可能是没必要的。 + UNITY_BRANCH + if((bit & isCustomDataBit) == 0) + { + return orignValue; + } + else + { + half4 customData = 0; + if((bit & Data12Bit)) + { + customData = cutstomData1; + + } + else + { + customData = customData2; + } + + if(bit & DataXYorZWBit) + { + if(bit & DataXZorYWBit) + { + return customData.x; + } + else + { + return customData.y; + } + } + else + { + if(bit & DataXZorYWBit) + { + return customData.z; + } + else + { + return customData.w; + } + } + } + return 999;//提示错误 + } + + + struct BaseUVs + { + float2 defaultUVChannel; + float2 specialUVChannel; + float2 uvAfterTwirlPolar; + float2 cylinderUV; + float2 mainTexUV; + float2 screenUV; + float2 worldPosUV; + float2 objectPosUV; + float2 sharedUV; + }; + + float2 GetUVByUVMode(uint flagProperty,uint flagTypeProperty,int flagPos,BaseUVs baseUVs) + { + flagProperty = flagProperty >> flagPos; + flagProperty &= 3; + flagTypeProperty = flagTypeProperty >> flagPos; + flagTypeProperty &= 3; + switch (flagTypeProperty) + { + case 0: + switch(flagProperty) + { + case 0: + return baseUVs.defaultUVChannel; + case 1: + return baseUVs.specialUVChannel; + case 2: + return baseUVs.uvAfterTwirlPolar; + case 3: + return baseUVs.cylinderUV; + default: + return baseUVs.defaultUVChannel; + } + case 1: + switch(flagProperty) + { + case 0: + return baseUVs.mainTexUV; + case 1: + return baseUVs.screenUV; + case 2: + return baseUVs.worldPosUV; + case 3: + return baseUVs.objectPosUV; + default: + return baseUVs.defaultUVChannel; + } + case 2: + switch(flagProperty) + { + case 0: + return baseUVs.sharedUV; + default: + return baseUVs.defaultUVChannel; + } + default: + return baseUVs.defaultUVChannel; + } + } + + half Blend_HardLight(half Base, half Blend) + { + half result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend); + half result2 = 2.0 * Base * Blend; + half zeroOrOne = step(Blend, 0.5); + half Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1; + return Out; + } + + #define FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND (0*3) + #define FLAG_BIT_PNOISE_BLEND_POS_0_MASK (1*3) + #define FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE (2*3) + #define FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT (3*3) + #define FLAG_BIT_PNOISE_BLEND_POS_0_MAINTEX (4*3) + + half BlendPNoise(uint flagProperty,int flagPos,half source,half pNoise,half opacity) + { + flagProperty = flagProperty >> flagPos; + flagProperty &= 7; + switch(flagProperty) + { + case 0: + return source; + case 1: + return lerp(source,pNoise*source,opacity); + case 2: + return lerp(source,min(pNoise,source),opacity); + case 3: + return lerp(source,Blend_HardLight(source,pNoise),opacity); + default: + return source; + } + } + + //ForDistort + half2 BlendPNoise(uint flagProperty,int flagPos,half2 source,half2 pNoise,half opacity) + { + flagProperty = flagProperty >> flagPos; + flagProperty &= 7; + switch(flagProperty) + { + case 0: + return source; + case 1: + return lerp(source,pNoise*source,opacity); + case 2: + return lerp(source,min(pNoise,source),opacity); + case 3: + return lerp(source,Blend_HardLight(source,pNoise),opacity); + default: + return source; + } + } + + + +#endif diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderFlags.hlsl.meta b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderFlags.hlsl.meta new file mode 100644 index 00000000..ed5ba709 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderFlags.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2813ce2207b94f57be1d1c91d9a21023 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderForwardPass.hlsl b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderForwardPass.hlsl new file mode 100644 index 00000000..bb5248a2 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderForwardPass.hlsl @@ -0,0 +1,1287 @@ +#ifndef NBSHADER_FORWARD_PASS + #define NBSHADER_FORWARD_PASS + #include "NBShaderInput.hlsl" + #include "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl" + #include "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl" + + #if defined(NB_DEPTH_ONLY_PASS) || defined(NB_SHADOW_CASTER_PASS) + #define NB_DEPTH_SHADOW_PASS + #endif + + #if defined(NB_SHADOW_CASTER_PASS) + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" + float3 _LightDirection; + float3 _LightPosition; + #endif + + + /////////////////////////////////////////////////////////////////////////////// + // Vertex and Fragment functions // + + struct ParticleFragmentOutput + { + half4 color : SV_Target; + #if defined(_OVERRIDE_Z) + float depth : SV_Depth; + #endif + }; + + #if defined(_OVERRIDE_Z) + float OverrideZToDeviceDepth() + { + float nearClip = _ProjectionParams.y; + float farClip = _ProjectionParams.z; + float eyeDepth = clamp(_OverrideZValue, nearClip, farClip); + + if (unity_OrthoParams.w == 0) + { + float reciprocalEyeDepth = rcp(max(eyeDepth, 1e-6)); + return saturate((reciprocalEyeDepth - _ZBufferParams.w) / _ZBufferParams.z); + } + + float linearDepth = saturate((eyeDepth - nearClip) / max(farClip - nearClip, 1e-6)); + #if UNITY_REVERSED_Z + return 1.0 - linearDepth; + #else + return linearDepth; + #endif + } + #endif + + ParticleFragmentOutput MakeParticleFragmentOutput(half4 color) + { + ParticleFragmentOutput output; + output.color = color; + #if defined(_OVERRIDE_Z) + output.depth = OverrideZToDeviceDepth(); + #endif + return output; + } + + + + VaryingsParticle vertParticleUnlit(AttributesParticle input) + { + VaryingsParticle output = (VaryingsParticle)0; + + output.VaryingsP_Custom1 = input.Custom1; + output.VaryingsP_Custom2 = input.Custom2; + + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + time = _Time.y; + + float4 positionOS = input.vertex; + float3 normalOS = input.normalOS; + #if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) || defined(_FX_LIGHT_MODE_SIX_WAY) + float4 tangentOS = input.tangentOS; + #endif + #ifdef _CUSTOM_LOCAL_TRANSFORM + positionOS.xyz = TransformWorldToObject_NB(input.vertex.xyz); + normalOS = TransformWorldToObjectNormal_NB(input.normalOS); + #if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) || defined(_FX_LIGHT_MODE_SIX_WAY) + tangentOS.xyz = TransformWorldToObjectDir_NB(input.tangentOS.xyz); + #endif + #endif + ApplyVAT(input, positionOS, normalOS); + // position ws is used to compute eye depth in vertFading + output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz); + output.positionOS.xyz = positionOS; + + output.clipPos = TransformObjectToHClip_NB(positionOS.xyz); + + float unityFogFactor = ComputeFogFactor(output.clipPos.z); + + output.positionWS.w = unityFogFactor; + + output.color = TryLinearize(input.color); + + // output.viewDirWS = GetWorldSpaceNormalizeViewDir(output.positionWS.xyz); + output.normalWSAndAnimBlend.xyz = TransformObjectToWorldNormal_NB(normalOS.xyz); + + #if defined(_PARALLAX_MAPPING)||defined(_NORMALMAP)||defined(_FX_LIGHT_MODE_SIX_WAY) + real sign = tangentOS.w * GetCustomLocalOddNegativeScale(); + half3 tangentWS = TransformObjectToWorldDir_NB(tangentOS.xyz); + #if (defined(_PARALLAX_MAPPING) || defined(_NORMALMAP)) && !defined(_FX_LIGHT_MODE_SIX_WAY) + output.tangentWS = half4(tangentWS,sign); + #endif + #endif + + + #ifndef _FX_LIGHT_MODE_UNLIT + #ifdef _FX_LIGHT_MODE_SIX_WAY + float3 bitangent = sign * cross(output.normalWSAndAnimBlend.xyz, tangentWS); + half3 bakeDiffuseLighting0; + half3 bakeDiffuseLighting1; + half3 bakeDiffuseLighting2; + half3 backBakeDiffuseLighting0; + half3 backBakeDiffuseLighting1; + half3 backBakeDiffuseLighting2; + GetSixWayBakeDiffuseLight(output.normalWSAndAnimBlend.xyz,tangentWS,bitangent, + bakeDiffuseLighting0,bakeDiffuseLighting1,bakeDiffuseLighting2, + backBakeDiffuseLighting0,backBakeDiffuseLighting1,backBakeDiffuseLighting2); + + output.bakeDiffuseLighting0 = half4(bakeDiffuseLighting0,tangentWS.x); + output.bakeDiffuseLighting1 = half4(bakeDiffuseLighting1,tangentWS.y); + output.bakeDiffuseLighting2 = half4(bakeDiffuseLighting2,tangentWS.z); + output.backBakeDiffuseLighting0 = half4(backBakeDiffuseLighting0,sign); + output.backBakeDiffuseLighting1 = half4(backBakeDiffuseLighting1,0); + output.backBakeDiffuseLighting2 = half4(backBakeDiffuseLighting2,0); + + #else + OUTPUT_SH(output.normalWSAndAnimBlend.xyz, output.vertexSH); + #ifdef _ADDITIONAL_LIGHTS_VERTEX + output.vertexLight = VertexLighting(output.positionWS.xyz, output.normalWSAndAnimBlend.xyz); + #endif + #endif + #endif + + + + // UNITY_FLATTEN + // Fresnel enable is keyword-driven by _FRESNEL. + // { + // output.fresnelViewDir = output.viewDirWS; + // } + + output.texcoord.xy = input.texcoords.xy; + + //顶点处理的原则: + //Twirl和极坐标,贴花处理,在片段着色器层处理UV。 + //BaseMap,遮罩Mask,Noise,高光(自发光) 和极坐标处理相关。 + BaseUVs baseUVs; + if(!isProcessUVInFrag()) + { + + float2 specialUVInTexcoord3 = 0; + //如果同时在粒子系统里开启序列帧融帧和特殊UV通道模式。 + #if _FLIPBOOKBLENDING_ON + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD1)|CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2))) + { + specialUVInTexcoord3 = input.texcoordBlend.yz; + output.texcoord2AndSpecialUV.zw = specialUVInTexcoord3; + } + #endif + ParticleUVs particleUVs = (ParticleUVs)0; + float2 screenUV = output.clipPos.xy/output.clipPos.w; + screenUV = screenUV*0.5+0.5; + baseUVs = ProcessBaseUVs(input.texcoords,specialUVInTexcoord3,output.VaryingsP_Custom1,output.VaryingsP_Custom2,output.positionOS.xyz,output.positionWS,screenUV); + ParticleProcessUV(particleUVs,input.texcoords,output.VaryingsP_Custom1,output.VaryingsP_Custom2,baseUVs); + output.texcoord2AndSpecialUV.xy = particleUVs.animBlendUV; + output.texcoord2AndSpecialUV.zw= particleUVs.specUV; + output.texcoord.xy = particleUVs.mainTexUV; + output.texcoord.zw = particleUVs.maskMapUV; + + #if defined(_MASKMAP2_ON) || defined(_MASKMAP3_ON) + output.texcoordMaskMap2.xy = particleUVs.maskMap2UV; + output.texcoordMaskMap2.zw = particleUVs.maskMap3UV; + #endif + #if defined (_NORMALMAP) || defined(_COLOR_RAMP) + output.bumpTexAndColorRampMapTexcoord.xy = particleUVs.bumpTexUV; + output.bumpTexAndColorRampMapTexcoord.zw = particleUVs.colorRampMapUV; + + #endif + + #if defined (_EMISSION) || defined(_COLORMAPBLEND) + output.emissionColorBlendTexcoord.xy = particleUVs.emissionUV; + output.emissionColorBlendTexcoord.zw = particleUVs.colorBlendUV; + #endif + + #ifdef _NOISEMAP + output.noisemapTexcoord.xy = particleUVs.noiseMapUV; + output.noisemapTexcoord.zw = particleUVs.noiseMaskMapUV; + #endif + #if defined(_DISSOLVE) + output.dissolveTexcoord.xy = particleUVs.dissolve_uv; + output.dissolveTexcoord.zw = particleUVs.dissolve_mask_uv; + #endif + + #ifdef _PROGRAM_NOISE_ACTIVE + output.dissolveNoiseTexcoord.xy = particleUVs.dissolve_noise1_UV; + output.dissolveNoiseTexcoord.zw = particleUVs.dissolve_noise2_UV; + #endif + } + else + { + output.texcoord = input.texcoords; + #if _FLIPBOOKBLENDING_ON + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)) + { + output.texcoord2AndSpecialUV.zw = input.texcoordBlend.yz; + } + #endif + } + #ifdef _FLIPBOOKBLENDING_ON + //粒子帧融合的情况,兼容一下。 + output.normalWSAndAnimBlend.w = input.texcoordBlend.x; + #endif + + #if defined(_VERTEX_OFFSET) + { + BaseUVs baseUVsForVertexOffset; + if(!isProcessUVInFrag()) + { + baseUVsForVertexOffset = baseUVs; + } + else + { + float2 screenUV = output.clipPos.xy/output.clipPos.w; + screenUV = screenUV*0.5+0.5; + baseUVsForVertexOffset = ProcessBaseUVs(input.texcoords,0,output.VaryingsP_Custom1,output.VaryingsP_Custom2,positionOS,output.positionWS,screenUV); + } + + //因为极坐标和旋转会强制到Frag计算,所以顶点在这边特殊处理一遍。 + + _VertexOffset_Map_ST.z += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X,0,input.Custom1,input.Custom2); + _VertexOffset_Map_ST.w += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y,0,input.Custom1,input.Custom2); + _VertexOffset_Vec.z = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY,_VertexOffset_Vec.z,input.Custom1,input.Custom2); + + #if defined(_VERTEX_OFFSET_MASKMAP) + _VertexOffset_MaskMap_ST.z += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X,0,input.Custom1,input.Custom2); + _VertexOffset_MaskMap_ST.w += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y,0,input.Custom1,input.Custom2); + #endif + + float2 vertexOffsetUVs = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP,baseUVsForVertexOffset); + float2 vertexOffsetMaskUVs = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP,baseUVsForVertexOffset); + + half3 vertexOffsetOS = 0; + positionOS.xyz = VetexOffset(positionOS,vertexOffsetUVs,vertexOffsetMaskUVs,normalOS,vertexOffsetOS); + #ifdef NB_DEBUG_VERTEX_OFFSET + half3 vertexOffsetWS = TransformObjectToWorldDir_NB(vertexOffsetOS,false); + output.color = half4(abs(vertexOffsetWS),1); + #endif + output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz); + + //再算一遍 + output.positionWS.xyz = TransformObjectToWorld_NB(positionOS.xyz); + output.positionOS.xyz = positionOS; + output.clipPos = TransformObjectToHClip_NB(positionOS.xyz); + } + #endif + + #if defined(NB_SHADOW_CASTER_PASS) + #if _CASTING_PUNCTUAL_LIGHT_SHADOW + float3 lightDirectionWS = normalize(_LightPosition - output.positionWS.xyz); + #else + float3 lightDirectionWS = _LightDirection; + #endif + + output.clipPos = TransformWorldToHClip(ApplyShadowBias(output.positionWS.xyz, output.normalWSAndAnimBlend.xyz, lightDirectionWS)); + + #if UNITY_REVERSED_Z + output.clipPos.z = min(output.clipPos.z, UNITY_NEAR_CLIP_VALUE); + #else + output.clipPos.z = max(output.clipPos.z, UNITY_NEAR_CLIP_VALUE); + #endif + #endif + + #if !defined(NB_DEPTH_SHADOW_PASS) + UNITY_BRANCH + if(needEyeDepth()) + { + float4 ndc = output.clipPos*0.5f; + output.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w; + output.positionNDC.zw = output.clipPos.zw; + } + #endif + + return output; + } + + + #if defined(NB_SHADOW_CASTER_PASS) + uint NBShadowBayer2(uint x, uint y) + { + return (((x ^ y) & 1u) << 1) | (y & 1u); + } + + half NBShadowDitherMaskClip(float4 positionCS, half alpha) + { + uint x = (uint)positionCS.x & 3u; + uint y = (uint)positionCS.y & 3u; + uint bayer = NBShadowBayer2(x & 1u, y & 1u) * 4u + NBShadowBayer2((x >> 1) & 1u, (y >> 1) & 1u); + half coverage = floor(saturate(alpha) * 16.0); + return coverage - (half)bayer - 0.01; + } + #endif + + + ///////////////////////Fragment functions //////////////////////// + + ParticleFragmentOutput fragParticleUnlit(VaryingsParticle input, half facing : VFACE) + { + + #if !defined(NB_DEPTH_SHADOW_PASS) + float3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS.xyz); + input.normalWSAndAnimBlend.xyz = facing > 0 ? input.normalWSAndAnimBlend.xyz : -input.normalWSAndAnimBlend.xyz; + #endif + + + UNITY_SETUP_INSTANCE_ID(input); + #if !defined(NB_DEPTH_SHADOW_PASS) + #ifdef NB_DEBUG_VERTEX_OFFSET + return MakeParticleFragmentOutput(input.color); + #endif + #endif + + time = _Time.y; + + float2 screenUV = input.clipPos.xy / _ScaledScreenParams.xy; + + #if !defined(NB_DEPTH_SHADOW_PASS) + real sceneZBufferDepth = 0; + real sceneZ = 0; + + UNITY_BRANCH + if(needSceneDepth()) + { + #if UNITY_REVERSED_Z + sceneZBufferDepth = SampleSceneDepth(screenUV); + #else + // Adjust z to match NDC for OpenGL + sceneZBufferDepth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(screenUV)); + #endif + sceneZ = (unity_OrthoParams.w == 0) ? LinearEyeDepth(sceneZBufferDepth, _ZBufferParams) : LinearDepthToEyeDepth(sceneZBufferDepth);//场景当前深度 + } + + real thisZ = 0; + + + half3 positionVS = 0; + if(needPositionVS()) + { + positionVS = TransformWorldToView(input.positionWS); + } + + if(needEyeDepth()) + { + thisZ = (unity_OrthoParams.w == 0) ? LinearEyeDepth(input.positionNDC.z / input.positionNDC.w, _ZBufferParams) : -positionVS.z;//场景当前深度 + } + + + #ifdef _DEPTH_DECAL + float3 fragWorldPos = ComputeWorldSpacePosition(screenUV, sceneZBufferDepth, UNITY_MATRIX_I_VP); + float3 fragobjectPos = TransformWorldToObject_NB(fragWorldPos); + + float3 absFragObjectPos = abs(fragobjectPos); + half clipValue = step(absFragObjectPos.x,0.5); + clipValue *= step(absFragObjectPos.y,0.5); + clipValue *= step(absFragObjectPos.z,0.5); + half decalAlpha = NB_Remap (abs(fragobjectPos.y),0.1,0.5,1,0); + decalAlpha = decalAlpha*decalAlpha; + decalAlpha *= clipValue; + float2 decalUV = fragobjectPos.xz + 0.5; + #endif + #endif + + float4 uv = input.texcoord; + #if !defined(NB_DEPTH_SHADOW_PASS) + #ifdef _DEPTH_DECAL + uv.xy = decalUV; + #endif + #endif + + float2 MainTex_UV; + float3 blendUv; + blendUv.xy = input.texcoord2AndSpecialUV.xy; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) + { + blendUv.z = _AnimationSheetHelperBlendIntensity; + } + else + { + blendUv.z = input.normalWSAndAnimBlend.w; + } + float2 MaskMapuv; + float2 MaskMapuv2; + float2 MaskMapuv3; + float2 noiseMap_uv; + float2 noiseMaskMap_uv; + float2 colorBlendMap_uv; + float2 emission_uv; + float2 dissolve_uv; + float2 dissolve_mask_uv; + float4 dissolve_noise_uv; + float2 BumpTex_uv; + float2 colorRamp_uv; + + //如果同时在粒子系统里开启序列帧融帧和特殊UV通道模式。 + + if(isProcessUVInFrag()) + { + float2 specialUVInTexcoord3 = 0; + #if _FLIPBOOKBLENDING_ON + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2))) + { + specialUVInTexcoord3 = input.texcoord2AndSpecialUV.zw; + } + + #endif + ParticleUVs particleUVs = (ParticleUVs)0; + BaseUVs baseUVs = ProcessBaseUVs(uv,specialUVInTexcoord3,input.VaryingsP_Custom1,input.VaryingsP_Custom2,input.positionOS.xyz,input.positionWS.xyz,screenUV); + ParticleProcessUV(particleUVs,uv,input.VaryingsP_Custom1,input.VaryingsP_Custom2,baseUVs); + MainTex_UV.xy = particleUVs.mainTexUV; + blendUv.xy = particleUVs.animBlendUV; + MaskMapuv = particleUVs.maskMapUV; + MaskMapuv2 = particleUVs.maskMap2UV; + MaskMapuv3 = particleUVs.maskMap3UV; + emission_uv = particleUVs.emissionUV; + dissolve_uv = particleUVs.dissolve_uv; + dissolve_mask_uv = particleUVs.dissolve_mask_uv; + colorBlendMap_uv = particleUVs.colorBlendUV; + noiseMap_uv = particleUVs.noiseMapUV; + noiseMaskMap_uv = particleUVs.noiseMaskMapUV; + dissolve_noise_uv = float4(particleUVs.dissolve_noise1_UV,particleUVs.dissolve_noise2_UV); + BumpTex_uv = particleUVs.bumpTexUV; + colorRamp_uv = particleUVs.colorRampMapUV; + } + else + { + MainTex_UV = input.texcoord.xy; + MaskMapuv = input.texcoord.zw; + #if defined(_MASKMAP2_ON) || defined(_MASKMAP3_ON) + MaskMapuv2 = input.texcoordMaskMap2.xy; + MaskMapuv3 = input.texcoordMaskMap2.zw; + #endif + + #if defined (_NORMALMAP)||defined(_COLOR_RAMP) + BumpTex_uv = input.bumpTexAndColorRampMapTexcoord.xy; + colorRamp_uv = input.bumpTexAndColorRampMapTexcoord.zw; + #endif + + #ifdef _NOISEMAP + noiseMap_uv = input.noisemapTexcoord.xy; + noiseMaskMap_uv = input.noisemapTexcoord.zw; + #endif + + #if defined (_EMISSION) || defined(_COLORMAPBLEND) + emission_uv = input.emissionColorBlendTexcoord.xy; + colorBlendMap_uv = input.emissionColorBlendTexcoord.zw; + #endif + + #ifdef _DISSOLVE + dissolve_uv = input.dissolveTexcoord.xy; + dissolve_mask_uv = input.dissolveTexcoord.zw; + #endif + #ifdef _PROGRAM_NOISE_ACTIVE + dissolve_noise_uv = input.dissolveNoiseTexcoord; + #endif + } + + + half programNoise; + #ifdef _PROGRAM_NOISE_ACTIVE + half programSimpleNoise; + half programVoronoiNoise; + + #if defined(_PROGRAM_NOISE_SIMPLE) + { + programSimpleNoise = SimplexNoise(dissolve_noise_uv.xy,_Time.y*_DissolveVoronoi_Vec2.z); + programNoise = programSimpleNoise; + } + #endif + + #if defined(_PROGRAM_NOISE_VORONOI) + { + half cell; + Unity_Voronoi_float(dissolve_noise_uv.zw,_Time.y*_DissolveVoronoi_Vec2.w,1,programVoronoiNoise,cell); + programNoise = programVoronoiNoise ; + } + #endif + + #if defined(_PROGRAM_NOISE_SIMPLE) && defined(_PROGRAM_NOISE_VORONOI) + { + programNoise = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND,programSimpleNoise,programVoronoiNoise,_ProgramNoiseBaseBlendOpacity); + // Unity_Blend_HardLight_half(programSimpleNoise,programVoronoiNoise,_DissolveVoronoi_Vec2.x,programNoise); + } + #endif + + // half dissolveSample = dissolveValue; + // Unity_Blend_HardLight_half(overlayVoroni,dissolveSample,_DissolveVoronoi_Vec2.y,dissolveValue); + #ifdef NB_DEBUG_PNOISE + return MakeParticleFragmentOutput(half4(programNoise.xxx,1)); + #endif + + #endif + + half2 originUV = MainTex_UV; + + //预先处理好法线贴图部分 + half metallic = 1; + half smoothness = 1; + half3 normalTS = half3(0, 0, 1);//TODO + half3x3 tangentToWorld = (half3x3)0; + #if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) || defined(_FX_LIGHT_MODE_SIX_WAY) + half4 tangentWS = 0; + #if defined(_FX_LIGHT_MODE_SIX_WAY) + tangentWS = half4(input.bakeDiffuseLighting0.w,input.bakeDiffuseLighting1.w,input.bakeDiffuseLighting2.w,input.backBakeDiffuseLighting0.w); + #else + tangentWS = input.tangentWS; + #endif + #endif + #if defined(_PARALLAX_MAPPING) || defined(_NORMALMAP) + float sgn = tangentWS.w; // should be either +1 or -1 + float3 bitangent = sgn * cross(input.normalWSAndAnimBlend.xyz, tangentWS.xyz); + tangentToWorld = half3x3(tangentWS.xyz, bitangent.xyz, input.normalWSAndAnimBlend.xyz); + #endif + #ifdef _PARALLAX_MAPPING + float3 tangentViewDir = NBTransformWorldToTangentDir(viewDirWS, tangentToWorld, true); + MainTex_UV.xy = ParallaxOcclusionMapping(MainTex_UV, tangentViewDir); + #endif + #ifdef _NORMALMAP + half4 normalMapSample = SampleTexture2DWithWrapFlags(_BumpTex,BumpTex_uv,FLAG_BIT_WRAPMODE_BUMPTEX); + if (CheckLocalFlags(FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE)) + { + normalTS = UnpackNormalRGB(half4(normalMapSample.xy,1,1),_BumpScale); + metallic *= normalMapSample.z; + smoothness *= normalMapSample.w; + } + else + { + normalTS = UnpackNormalScale(half4(normalMapSample),_BumpScale); + } + + input.normalWSAndAnimBlend.xyz = normalize(TransformTangentToWorld(normalTS, tangentToWorld)); + #endif + + half2 cum_noise = 0; + // half2 cum_noise_xy = half2(0.5,0.5); + half3 screenDistort_Noise = half3(0,0,1);//xy:noise,z:mask; + half noiseMask = 1; + #if defined(_NOISEMAP) + #ifdef _DISTORT_REFRACTION + half3 refracVec = CustomRefract(-viewDirWS,input.normalWSAndAnimBlend.xyz,1/_RefractionIOR); + refracVec = TransformWorldToHClipDir(refracVec); + cum_noise = refracVec.xy; + // distortFlow = refracVec.xy * props._NormalRefractionBias; + #else + half4 noiseSample = SampleNoise(_NoiseOffset, _NoiseMap, noiseMap_uv, input.positionWS.xyz); + cum_noise = noiseSample.xy; + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON)) + { + cum_noise = cum_noise * 2 - 1; + } + noiseMask *= noiseSample.a; + _DistortionDirection.x += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + _DistortionDirection.y += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + #endif + #if defined(_NOISE_MASKMAP) + { + half4 noiseMaskSample = SampleTexture2DWithWrapFlags(_NoiseMaskMap,noiseMaskMap_uv,FLAG_BIT_WRAPMODE_NOISE_MASKMAP); + noiseMask *= GetColorChannel(noiseMaskSample,FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK); + } + #endif + _NoiseIntensity = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY,_NoiseIntensity,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + + cum_noise = cum_noise *_DistortionDirection.xy*_NoiseIntensity; + + #ifdef _PROGRAM_NOISE_ACTIVE + cum_noise = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT,cum_noise,programNoise,_DistortPNoiseBlendOpacity); + #endif + + + + #if defined(_SCREEN_DISTORT_MODE) + screenDistort_Noise.xy = cum_noise; + screenDistort_Noise.z = noiseMask; + #endif + // #if defined(_SCREEN_DISTORT_MODE) + // cum_noise_xy = cum_noise * _ScreenDistortIntensity; + // #endif + + cum_noise *= noiseMask; + + #ifdef NB_DEBUG_DISTORT + return MakeParticleFragmentOutput(half4(cum_noise,0,1)); + #endif + #endif + + // SampleAlbedo-------------------- + half4 albedo = 0; + + #if !defined(NB_DEPTH_SHADOW_PASS) + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_BACKCOLOR)) + { + _BaseColor = facing > 0 ? _BaseColor : _BaseBackColor; + } + #endif + + + Texture2D baseMap = _BaseMap; + + + + float2 mainTexNoise = cum_noise * _TexDistortion_intensity; + + MainTex_UV.xy += mainTexNoise;//主贴图纹理扭曲 + blendUv.xy += mainTexNoise; + + + UNITY_BRANCH + if (CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON) & !CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE)) + { + albedo = BlendTexture(_MainTex, MainTex_UV, blendUv) * _Color; + } + else + { + #if defined(_CHROMATIC_ABERRATION) + #if !defined(NB_DEPTH_SHADOW_PASS) + _DistortionDirection.z = GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY,_DistortionDirection.z,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + _DistortionDirection.z *= 0.1; + albedo = DistortionChoraticaberrat(baseMap,originUV,MainTex_UV,_DistortionDirection.z,FLAG_BIT_WRAPMODE_BASEMAP); + #else + albedo = BlendTexture(baseMap, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP); + #endif + #else + albedo = BlendTexture(baseMap, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP); + #endif + } + + // #ifndef _CAMERA_OPAQUE_DISTORT_PASS + + albedo.a = GetColorChannel(albedo,FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA); + + albedo *= _BaseColor ; + #if !defined(NB_DEPTH_SHADOW_PASS) + albedo.rgb *= _BaseColorIntensityForTimeline; + #endif + // #endif + + + // #endif + + half alpha = albedo.a; + half3 result = albedo.rgb; + #if !defined(NB_DEPTH_SHADOW_PASS) + UNITY_BRANCH + if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX)) + { + ColorAdjustment(result,alpha,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + } + #endif + + #ifdef _FX_LIGHT_MODE_SIX_WAY + float4 rigRTBkSample = BlendTexture(_RigRTBk, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP); + float4 rigLBtFSample = BlendTexture(_RigLBtF, MainTex_UV, blendUv,FLAG_BIT_WRAPMODE_BASEMAP); + #endif + + + //光照模式 + #ifndef _FX_LIGHT_MODE_UNLIT + + InputData inputData; + InitializeInputData(input, tangentToWorld,viewDirWS, inputData); + metallic *= _MaterialInfo.x; + half3 specular = 0; + smoothness *= _MaterialInfo.y; + half occlusion = 1; + half3 pbrEmission = 0; + // return half4(inputData.bakedGI,1); + #if defined (_FX_LIGHT_MODE_BLINN_PHONG) || defined(_FX_LIGHT_MODE_HALF_LAMBERT) + half4 specularGloss = _SpecularColor; + #ifdef _FX_LIGHT_MODE_BLINN_PHONG + half4 blinnPhong = UniversalFragmentBlinnPhong(inputData,result.rgb, specularGloss, smoothness, pbrEmission, alpha,normalTS); + #else //_FX_LIGHT_MODE_HALF_LAMBERT + half4 blinnPhong = UniversalFragmentHalfLambert(inputData,result.rgb, specularGloss, smoothness, pbrEmission, alpha,normalTS); + #endif + result = blinnPhong.rgb; + alpha = blinnPhong.a; + #elif _FX_LIGHT_MODE_PBR + half4 pbr = UniversalFragmentPBR(inputData,result.rgb, metallic, specular, smoothness, occlusion, pbrEmission, alpha); + result = pbr.rgb; + alpha = pbr.a; + #elif _FX_LIGHT_MODE_SIX_WAY + BSDFData bsdfData = (BSDFData)0; + bsdfData.absorptionRange = GetAbsorptionRange(_SixWayInfo.x); + bsdfData.diffuseColor = albedo; + bsdfData.normalWS = inputData.normalWS; + bsdfData.tangentWS = tangentWS; + bsdfData.rigRTBk = rigRTBkSample.xyz * INV_PI;//AccordingTo SixWayForwardPass + bsdfData.rigLBtF = rigLBtFSample.xyz * INV_PI;//AccordingTo SixWayForwardPass + bsdfData.bakeDiffuseLighting0 = input.bakeDiffuseLighting0.xyz; + bsdfData.bakeDiffuseLighting1 = input.bakeDiffuseLighting1.xyz; + bsdfData.bakeDiffuseLighting2 = input.bakeDiffuseLighting2.xyz; + bsdfData.backBakeDiffuseLighting0 = input.backBakeDiffuseLighting0.xyz; + bsdfData.backBakeDiffuseLighting1 = input.backBakeDiffuseLighting1.xyz; + bsdfData.backBakeDiffuseLighting2 = input.backBakeDiffuseLighting2.xyz; + bsdfData.emissionInput = rigLBtFSample.a; + GetSixWayEmission(bsdfData,_SixWayEmissionRamp,_SixWayEmissionColor,CheckLocalFlags1(FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP));//Init Emission + bsdfData.alpha = rigRTBkSample.a * _BaseColor.a; + + ModifyBakedDiffuseLighting(bsdfData,inputData.bakedGI); + + half4 sixWay = UniversalFragmentSixWay(inputData,bsdfData); + + + // half3 dir = _MainLightPosition.xyz; + // dir = TransformToLocalFrame(dir, bsdfData); + // return half4(dir,1); + + result = sixWay.rgb; + alpha = sixWay.a; + + #endif + + #ifdef _ADDITIONAL_LIGHTS_VERTEX + result.rgb *= input.vertexLight; + #endif + + // input.normalWSAndAnimBlend.xyz = inputData.normalWS; + #endif + + + #ifdef _MATCAP + // URP + half3 normalVS = mul(input.normalWSAndAnimBlend.xyz, (float3x3)UNITY_MATRIX_I_V); // 逆转置矩阵 + //half3 positionVS = TransformWorldToView(input.positionWS); + + + float3 r = reflect(positionVS, normalVS); + r = normalize(r); + float m = 2.828427f * sqrt(r.z + 1.0); + float2 matCapUV = r.xy / m + 0.5; + half3 matCapSample = SAMPLE_TEXTURE2D(_MatCapTex,sampler_linear_clamp,matCapUV); + + matCapSample *= _MatCapColor.rgb; + + half3 matCapMutilResult = result * matCapSample; + half3 matAddResult = result + matCapSample; + half3 matCapResult = lerp(matAddResult,matCapMutilResult,_MatCapInfo.x); + + result = lerp(result,matCapResult,_MatCapColor.a); + #endif + + + + //流光部分 + half4 emission = half4(0, 0, 0,1); + #if defined(_EMISSION) + #ifdef _NOISEMAP + emission_uv += cum_noise * _Emi_Distortion_intensity; + #endif + // emission = tex2D_TryLinearizeWithoutAlphaFX(_EmissionMap,emission_uv); + emission = SampleTexture2DWithWrapFlags(_EmissionMap,emission_uv,FLAG_BIT_WRAPMODE_EMISSIONMAP); + emission.xyz *= emission.a; + _EmissionMapColor *= _EmissionMapColorIntensity; + emission.xyz *= _EmissionMapColor; + + #endif + + result += emission; + + + #if defined(_COLOR_RAMP) + half rampValue = 0; + #if defined(_COLOR_RAMP_MAP) + half4 RampColorSample = SampleTexture2DWithWrapFlags(_RampColorMap,colorRamp_uv,FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP); + rampValue = GetColorChannel(RampColorSample,FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP); + #else + const int rampColorWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP); + if (rampColorWrapMode == 0 || rampColorWrapMode == 2) + { + rampValue = frac(colorRamp_uv.x); + } + else + { + rampValue = saturate(colorRamp_uv.x); + } + #endif + + int colorRampColorCount = _RampColorCount & 0xFFFF; + + int colorRampAlphaCount = _RampColorCount >> 16; + + half4 rampColor; + rampColor.rgb = SamplePackedGradientColor(_RampColor0, _RampColor1, _RampColor2, _RampColor3, _RampColor4, _RampColor5, colorRampColorCount, rampValue); + rampColor.a = SamplePackedGradientAlpha(_RampColorAlpha0, _RampColorAlpha1, _RampColorAlpha2, colorRampAlphaCount, rampValue); + + rampColor *= _RampColorBlendColor; + + if (CheckLocalFlags(FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD)) + { + result += rampColor; + alpha += rampColor.a; + } + else + { + result *= rampColor; + alpha *= rampColor.a; + } + #endif + + + + //溶解部分 + #if defined(_DISSOLVE) + #ifdef _NOISEMAP + dissolve_uv += cum_noise * _DissolveOffsetRotateDistort.w; + + #if defined(_DISSOLVE_MASK) + dissolve_mask_uv += cum_noise * _DissolveOffsetRotateDistort.w; + #endif + #endif + + half4 dissolveMapSample = SampleTexture2DWithWrapFlags(_DissolveMap,dissolve_uv,FLAG_BIT_WRAPMODE_DISSOLVE_MAP); + + half dissolveValue = GetColorChannel(dissolveMapSample,FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP); + + #ifdef _PROGRAM_NOISE_ACTIVE + dissolveValue = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE,dissolveValue,programNoise,_DissolvePNoiseBlendOpacity); + #endif + + + dissolveValue = pow(dissolveValue,_Dissolve.y); + + + + + half dissolveMaskValue = 0; + half dissolveMaskStrength = 0; + #if defined(_DISSOLVE_MASK) + { + half4 dissolveMaskSample = SampleTexture2DWithWrapFlags(_DissolveMaskMap,dissolve_mask_uv,FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP); + dissolveMaskValue = GetColorChannel(dissolveMaskSample,FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP); + dissolveMaskStrength = _Dissolve.z + GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + + if (_DissolveMaskMode < 0.5) + { + dissolveMaskValue = lerp(dissolveValue, dissolveMaskValue, dissolveMaskStrength); + dissolveValue = (dissolveValue +dissolveMaskValue)*0.5;//Smart Way By Panda + } + } + #endif + + #ifdef NB_DEBUG_DISSOLVE //后续Test类的关键字要找机会排除 + return MakeParticleFragmentOutput(half4(dissolveValue.rrr,1)); + #endif + half dissolveStrenth = _Dissolve.x + GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + + half invSoftStep = 1/_Dissolve.w; + half dissolveValueBeforeSoftStep = dissolveValue - ((dissolveStrenth)*(invSoftStep + 1)-1)*_Dissolve.w ; + dissolveValue = dissolveValue*invSoftStep -(1+invSoftStep)*dissolveStrenth +1; + // dissolveValue = smoothstep(dissolveStrenth-_Dissolve.w,dissolveStrenth,dissolveValue);//Smart Way By Panda + + + dissolveValue = saturate(dissolveValue); + #if defined(_DISSOLVE_MASK) + if(_DissolveMaskMode > 0.5) + { + dissolveMaskStrength = dissolveMaskStrength -1; + dissolveMaskValue = saturate(dissolveMaskValue - dissolveMaskStrength); + dissolveValue = lerp(1, dissolveValue, dissolveMaskValue); + } + #endif + + alpha *= dissolveValue; + #if !defined(NB_DEPTH_SHADOW_PASS) + #if defined(_DISSOLVE_RAMP) + { + // half rampRange = (dissolveValueBeforeSoftStep - _Dissolve_Vec2.x)*_Dissolve_Vec2.y; + half rampRange = dissolveValueBeforeSoftStep; + rampRange = rampRange * _DissolveRampMap_ST.x +_DissolveRampMap_ST.z; + + half4 rampSample ; + #if defined(_DISSOLVE_RAMP_MAP) + rampSample = SampleTexture2DWithWrapFlags(_DissolveRampMap,half2(rampRange,0.5),FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP); + #else + int dissolveRampColorCount = _DissolveRampCount & 0xFFFF; + + int dissolveRampAlphaCount = _DissolveRampCount >> 16; + + const int rampWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP); + if (rampWrapMode == 0 || rampWrapMode == 2) + { + rampRange = frac(rampRange); + } + else + { + rampRange = saturate(rampRange); + } + + + rampSample.rgb = SamplePackedGradientColor(_DissolveRampColor0, _DissolveRampColor1, _DissolveRampColor2, _DissolveRampColor3, _DissolveRampColor4, _DissolveRampColor5, dissolveRampColorCount, rampRange); + rampSample.a = SamplePackedGradientAlpha(_DissolveRampAlpha0, _DissolveRampAlpha1, _DissolveRampAlpha2, dissolveRampAlphaCount, rampRange); + #endif + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY)) + { + result = result * lerp(1,rampSample.rgb*_DissolveRampColor.rgb,rampSample.a*_DissolveRampColor.a); + } + else + { + result = lerp(result,rampSample.rgb*_DissolveRampColor.rgb,rampSample.a*_DissolveRampColor.a); + } + } + #endif + + + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK)) + { + half lineMask = dissolveValueBeforeSoftStep;//SmoothStep要优化 + lineMask = saturate(NB_Remap01(lineMask,_Dissolve_Vec2.x-_Dissolve_Vec2.y,_Dissolve_Vec2 + _Dissolve_Vec2.y)); + lineMask = 1- lineMask; + + result = lerp(result,_DissolveLineColor.rgb,lineMask*_DissolveLineColor.a); + } + #endif + // + + + #endif + + //颜色渐变 + #ifdef _COLORMAPBLEND + #if defined(_NOISEMAP) + colorBlendMap_uv += cum_noise * _ColorBlendVec.x; //加入扭曲效果 + #endif + half4 colorBlend = SampleTexture2DWithWrapFlags(_ColorBlendMap,colorBlendMap_uv,FLAG_BIT_WRAPMODE_COLORBLENDMAP); + colorBlend.rgb = colorBlend.rgb * _ColorBlendColor.rgb; + colorBlend.a = lerp(1,colorBlend.a*_ColorBlendColor.a,_ColorBlendVec.z); + if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE)) + { + result *= colorBlend.rgb; + alpha *= colorBlend.a; + } + else + { + result.rgb = lerp(result.rgb,result.rgb * colorBlend.rgb,colorBlend.a); + } + #endif + + //遮罩部分 + #if defined(_MASKMAP_ON) + + #if defined(_NOISEMAP) + MaskMapuv += cum_noise * _MaskDistortion_intensity; //加入扭曲效果 + #endif + + half mask1 = 1; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT)) + { + const int maskMapWrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP); + half maskMapTimeValue; + if (maskMapWrapMode == 0 || maskMapWrapMode == 2) + { + maskMapTimeValue = frac(MaskMapuv.x); + } + else + { + maskMapTimeValue = saturate(MaskMapuv.x); + } + + int maskMapAlphaCount = _MaskMapGradientCount; + mask1 = SamplePackedGradientAlpha(_MaskMapGradientFloat0, _MaskMapGradientFloat1, _MaskMapGradientFloat2, maskMapAlphaCount, maskMapTimeValue); + } + else + { + half4 maskmap1Sample = SampleTexture2DWithWrapFlags(_MaskMap, MaskMapuv,FLAG_BIT_WRAPMODE_MASKMAP); + mask1 = GetColorChannel(maskmap1Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1); + + } + + #if defined(_MASKMAP2_ON) + { + half mask2 = 1; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT)) + { + const int maskMap2WrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP2); + half maskMap2TimeValue; + if (maskMap2WrapMode == 0 || maskMap2WrapMode == 3) + { + maskMap2TimeValue = frac(MaskMapuv2.y); + } + else + { + maskMap2TimeValue = saturate(MaskMapuv2.y); + } + + int maskMap2AlphaCount = _MaskMap2GradientCount; + mask2 = SamplePackedGradientAlpha(_MaskMap2GradientFloat0, _MaskMap2GradientFloat1, _MaskMap2GradientFloat2, maskMap2AlphaCount, maskMap2TimeValue); + } + else + { + half4 maskMap2Sample = SampleTexture2DWithWrapFlags(_MaskMap2, MaskMapuv2,FLAG_BIT_WRAPMODE_MASKMAP2); + mask2 = GetColorChannel(maskMap2Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2); + } + mask1 *= mask2; + } + #endif + + #if defined(_MASKMAP3_ON) + { + half mask3 = 1; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT)) + { + const int maskMap3WrapMode = CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_MASKMAP3); + half maskMap3TimeValue; + if (maskMap3WrapMode == 0 || maskMap3WrapMode == 2) + { + maskMap3TimeValue = frac(MaskMapuv3.x); + } + else + { + maskMap3TimeValue = saturate(MaskMapuv3.x); + } + + int maskMap3AlphaCount = _MaskMap3GradientCount; + mask3 = SamplePackedGradientAlpha(_MaskMap3GradientFloat0, _MaskMap3GradientFloat1, _MaskMap3GradientFloat2, maskMap3AlphaCount, maskMap3TimeValue); + } + else + { + half4 maskMap3Sample = SampleTexture2DWithWrapFlags(_MaskMap3, MaskMapuv3,FLAG_BIT_WRAPMODE_MASKMAP3); + mask3 = GetColorChannel(maskMap3Sample,FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3); + } + mask1 *= mask3; + } + #endif + + #ifdef _PROGRAM_NOISE_ACTIVE + mask1 = BlendPNoise(_W9ParticleShaderPNoiseBlendFlag,FLAG_BIT_PNOISE_BLEND_POS_0_MASK,mask1,programNoise,_MaskPNoiseBlendOpacity); + #endif + + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MASK_REFINE)) + { + mask1 = pow(mask1,_MaskRefineVec.x); + mask1 = mask1 * _MaskRefineVec.y; + mask1 += _MaskRefineVec.z; + } + + mask1 = lerp(1,mask1,_MaskMapVec.x); + mask1 = saturate(mask1); + + #ifdef NB_DEBUG_MASK + return MakeParticleFragmentOutput(half4(mask1.rrr,1)); + #endif + + + alpha *= mask1; //mask边缘 + #endif + + //菲涅 + + #if !defined(NB_DEPTH_SHADOW_PASS) + #if defined(_FRESNEL) + { + half fresnelValue = 0; + if(!ignoreFresnel()) + { + half3 fresnelDir = normalize(viewDirWS+_FresnelRotation.rgb); + + half dotNV = dot(fresnelDir,input.normalWSAndAnimBlend.xyz) ; + fresnelValue = dotNV; + + + _FresnelUnit.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET,0,input.VaryingsP_Custom1,input.VaryingsP_Custom2);; + + // half fresnelHardness = - _FresnelUnit.w*0.5 +0.5; + fresnelValue = NB_Remap(fresnelValue,_FresnelUnit.x,_FresnelUnit.x + 1.01 - _FresnelUnit.w,0,1); + UNITY_BRANCH + if(!CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON)) + { + fresnelValue = 1- fresnelValue; + } + fresnelValue = pow(fresnelValue,_FresnelUnit.y); + + + // fresnelValue = smoothstep(0.5-fresnelHardness,0.5+fresnelHardness,fresnelValue); + } + + #ifdef NB_DEBUG_FRESNEL + return MakeParticleFragmentOutput(half4(fresnelValue.rrr*_FresnelUnit.z,1)); + #endif + + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_FADE_ON)) + { + fresnelValue *= alpha; + alpha = lerp(alpha,fresnelValue,_FresnelUnit.z); + } + else + { + float fresnelColorIntensity = fresnelValue*_FresnelColor.a*_FresnelUnit.z; + + result = lerp(result,_FresnelColor.rgb,fresnelColorIntensity); + if (!CheckLocalFlags(FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA)) + { + alpha = max(alpha,fresnelColorIntensity);//颜色要不要不被主贴图Alpha影响呢? + } + + } + + } + #endif + + #if defined(_DEPTH_OUTLINE) + { + half depthOutlineValue = 1- SoftParticles(_DepthOutline_Vec.x, _DepthOutline_Vec.y, sceneZ,thisZ); + depthOutlineValue *= _DepthOutline_Color.a; + half3 originResult = result; + //如何在一个pass里,完美的给出两个颜色的Fade。这个问题,没有想清楚。 + result = lerp(result,_DepthOutline_Color.rgb,clamp(depthOutlineValue*3,0,1)); + result = lerp(result,originResult,clamp(alpha-depthOutlineValue,0,1)); + alpha = max(alpha,depthOutlineValue); + + } + #endif + + + + + + + + //可以看https://www.cyanilux.com/tutorials/depth/ + // float4 projectedPosition = input.positionNDC; + // float thisZ1 = LinearEyeDepth(projectedPosition.z / projectedPosition.w, _ZBufferParams); + + + #if defined(_DISTANCE_FADE) + { + half fade = DepthFactor(thisZ, _Fade.x, _Fade.y); + alpha *= fade; + } + #endif + + + #if defined(_SOFTPARTICLES_ON) + + half softAlpha = SoftParticles(SOFT_PARTICLE_NEAR_FADE, SOFT_PARTICLE_INV_FADE_DISTANCE, sceneZ,thisZ); + alpha *= softAlpha; + + #endif + #endif + + + + + + + + //和粒子颜色信息运算。雨轩:乘顶点色。 + if(!CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR)) + { + #if !defined(NB_DEPTH_SHADOW_PASS) + result *= input.color.rgb; + #endif + alpha *= input.color.a; + } + // 程序额外的颜色 + #if !defined(NB_DEPTH_SHADOW_PASS) + result *= _ColorA.rgb; + #endif + alpha *= _ColorA.a; + // // alpha *= _ColorA * 0.8; + + + #if !defined(NB_DEPTH_SHADOW_PASS) + #ifdef _DEPTH_DECAL + alpha *= decalAlpha; + #endif + + half3 beforeFogResult = result; + result = MixFog(result,input.positionWS.w); + result = lerp(beforeFogResult, result, _fogintensity); + + UNITY_BRANCH + if (!CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX)) + { + ColorAdjustment(result,alpha,input.VaryingsP_Custom1,input.VaryingsP_Custom2); + } + + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_LINEARTOGAMMA_ON)) + { + result.rgb = LinearToGammaSpace(result.rgb); + } + #endif + + + alpha *= _AlphaAll; + alpha = saturate(alpha); + + #if defined(NB_DEPTH_ONLY_PASS) + #ifdef _ALPHATEST_ON + clip(alpha - _Cutoff); + #endif + return MakeParticleFragmentOutput(half4(input.clipPos.z, 0, 0, 0)); + #elif defined(NB_SHADOW_CASTER_PASS) + #ifdef _ALPHATEST_ON + clip(alpha - _Cutoff); + #endif + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_TRANSPARENT_MODE)) + { + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_TRANSPARENT_SHADOW_DITHER)) + { + clip(NBShadowDitherMaskClip(input.clipPos, alpha)); + } + else + { + clip(alpha - 0.5); + } + } + + return MakeParticleFragmentOutput(0); + #endif + + half alphaStrength = alpha; + #if defined (_ALPHAPREMULTIPLY_ON) || defined(_ALPHAMODULATE_ON) + result *= alpha; + #ifdef _ALPHAPREMULTIPLY_ON + alpha *= _AdditiveToPreMultiplyAlphaLerp; + #endif + #endif + + + #ifdef _SCREEN_DISTORT_MODE + + //在这里可以进行Alpha的修改 + half screenDistortAlpha = alphaStrength * screenDistort_Noise.z; + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE)) + { + screenDistortAlpha = pow(screenDistortAlpha,_ScreenDistortAlphaPow); + screenDistortAlpha *= _ScreenDistortAlphaMulti; + screenDistortAlpha += _ScreenDistortAlphaAdd; + } + #ifdef _DEFERRED_DISTORT_PASS + result = half3(screenDistort_Noise.xy,1.0); + alpha = screenDistortAlpha * _ScreenDistortIntensity; + #endif + + #ifdef _CAMERA_OPAQUE_DISTORT_PASS + float2 screenDistortUV = screenUV; + screenDistortUV = screenDistortUV + screenDistort_Noise.xy * screenDistortAlpha * _ScreenDistortIntensity; + half4 screenTexDistortSample = SampleTexture2DWithWrapFlags(_CameraOpaqueTexture,screenDistortUV,FLAG_BIT_WRAPMODE_BASEMAP); + result = screenTexDistortSample.xyz; + alpha = 1; + // alpha = screenTexDistortSample.a; + #endif + + #endif + + + + + half4 color = half4(result, alpha); + + + + #ifdef _ALPHATEST_ON + clip(color.a - _Cutoff); + + #endif + + color = min(color,1000); + + + return MakeParticleFragmentOutput(color); + } + +#endif diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderForwardPass.hlsl.meta b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderForwardPass.hlsl.meta new file mode 100644 index 00000000..829e1035 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderForwardPass.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5bc5a11b8453489893769021c54525b0 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderInput.hlsl b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderInput.hlsl new file mode 100644 index 00000000..818eb2ef --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderInput.hlsl @@ -0,0 +1,1763 @@ +#ifndef NBSHADER_INPUT + #define NBSHADER_INPUT + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "NBShaderFlags.hlsl" + + #if defined(_PROGRAM_NOISE) && (defined(_PROGRAM_NOISE_SIMPLE) || defined(_PROGRAM_NOISE_VORONOI)) + #define _PROGRAM_NOISE_ACTIVE + #endif + + + //---------------particleInput------------------- + CBUFFER_START(UnityPerMaterial) + float4 _SoftParticleFadeParams; + float4 _CameraFadeParams; + // #ifdef _INTERSECT_ON + float _IntersectRadius; + half4 _IntersectColor; + // #endif + half _AdditiveToPreMultiplyAlphaLerp; + half _Saturability; + half _HueShift; + half _Contrast; + half3 _ContrastMidColor; + half4 _BaseMapColorRefine; + half _AlphaAll; + float4 _BaseMap_ST; + float4 _BaseMap_AnimationSheetBlend_ST;//20240826 暂时只是给AnimationSheetHelper用。 + half _AnimationSheetHelperBlendIntensity; + float4 _MaskMap_ST; + half4 _BaseColor; + half4 _BaseBackColor; + half _BaseColorIntensityForTimeline; + half4 _EmissionMap_ST; + half4 _NoiseMap_ST; + half4 _NoiseMaskMap_ST; + half4 _DistortionDirection; + half4 _BaseColorAddSubDiff; + half _fogintensity; + half _Emi_Distortion_intensity; + half _BaseMapUVRotation; + half _BaseMapUVRotationSpeed; + float _MaskMapUVRotation; + float _NoiseMapUVRotation; + half _ScreenDistortIntensity; + half _ScreenDistortAlphaPow; + half _ScreenDistortAlphaAdd; + half _ScreenDistortAlphaMulti; + half _NoiseIntensity; + half _RefractionIOR; + half _uvRapSoft; + half4 _EmissionMapColor; + half _EmissionMapColorIntensity; + + + //--------------光照部分------------- + float4 _BumpTex_ST; + half _BumpScale; + half4 _MaterialInfo; + half4 _SpecularColor; + //-----------SixWayLight---------- + half4 _SixWayInfo; + half4 _SixWayEmissionColor; + + half4 _MatCapColor; + half4 _MatCapInfo; + + half _EdgeFade; + half4 _NoiseOffset; + half4 _EmissionMapUVOffset; + half _EmissionMapUVRotation; + half _EmissionSelfAlphaWeight; + half _TexDistortion_intensity; + // //half _RJ_Distortion_intensity; + // half _XianXingCH_UVRota; + // half _jingxiangCH_dire; + + half _MaskDistortion_intensity; + half4 _BaseMapMaskMapOffset; + half4 _MaskMapOffsetAnition; + half4 _MaskMap3OffsetAnition; + half4 _MaskMapVec; + half4 _MaskRefineVec; + + int _MaskMapGradientCount; + half4 _MaskMapGradientFloat0; + half4 _MaskMapGradientFloat1; + half4 _MaskMapGradientFloat2; + int _MaskMap2GradientCount; + half4 _MaskMap2GradientFloat0; + half4 _MaskMap2GradientFloat1; + half4 _MaskMap2GradientFloat2; + int _MaskMap3GradientCount; + half4 _MaskMap3GradientFloat0; + half4 _MaskMap3GradientFloat1; + half4 _MaskMap3GradientFloat2; + + float4 _PCCenter; + float4 _TWParameter; + float _TWStrength; + float4 _Fade; + float _OverrideZValue; + float _MaskMapRotationSpeed; + + + half _FrePower; + half _FresnelInOutSlider; + half4 _FresnelRotation; + half _FresnelSelfAlphaWeight; + half4 _FresnelUnit; + half4 _FresnelUnit2; + half4 _DepthOutline_Vec; + half4 _DepthOutline_Color; + half4 _FresnelColor; + half4 _ColorA; + float4 _ClipRect; + + float4 _CylinderMatrix0; + float4 _CylinderMatrix1; + float4 _CylinderMatrix2; + float4 _CylinderMatrix3; + + half4 _Color; + float4 _UI_MainTex_ST;//在UI中,RawImage组件的功能和正常的TexST不一致,所以这里使用另外传的方式。 + float4 _MainTex_Reverse_ST; + + half _Cutoff; + + float4 _MaskMap2_ST; + float4 _MaskMap3_ST; + + float time; + half _FresnelFadeDistance; + + half4 LB_RT; + + half4 _Dissolve; + half4 _DissolveMap_ST; + half4 _DissolveOffsetRotateDistort; + half4 _DissolveMaskMap_ST; + half _DissolveMaskMode; + + half4 _DissolveLineColor; + half4 _DissolveRampColor; + float4 _DissolveVoronoi_Vec; + half4 _DissolveVoronoi_Vec2; + float4 _DissolveVoronoi_Vec3; + float4 _DissolveVoronoi_Vec4; + half4 _DissolveRampMap_ST; + half4 _Dissolve_Vec2; + half _ProgramNoise_Rotate; + + half4 _SharedUV_ST; + half4 _SharedUV_Vec; + // half _SharedUV_Distort_Intensity; + + half4 _ColorBlendMap_ST; + float4 _ColorBlendMapOffset; + half4 _ColorBlendColor; + half4 _ColorBlendVec; + + half4 _RampColor0; + half4 _RampColor1; + half4 _RampColor2; + half4 _RampColor3; + half4 _RampColor4; + half4 _RampColor5; + half4 _RampColorAlpha0; + half4 _RampColorAlpha1; + half4 _RampColorAlpha2; + uint _RampColorCount; + half4 _RampColorBlendColor; + float4 _RampColorMapOffset; + half4 _RampColorMap_ST; + + half4 _DissolveRampColor0; + half4 _DissolveRampColor1; + half4 _DissolveRampColor2; + half4 _DissolveRampColor3; + half4 _DissolveRampColor4; + half4 _DissolveRampColor5; + half4 _DissolveRampAlpha0; + half4 _DissolveRampAlpha1; + half4 _DissolveRampAlpha2; + uint _DissolveRampCount; + + + half3 _VertexOffset_Vec; + half3 _VertexOffset_CustomDir; + half4 _VertexOffset_Map_ST; + + half4 _VertexOffset_MaskMap_ST; + half3 _VertexOffset_MaskMap_Vec; + + float _VAT_Toggle; + float _VATMode; + float _ImportScale; + float _TyFlowVATSubMode; + float _DeformingSkin; + float _SkinBoneCount; + float _RGBAEncoded; + float _RGBAHalf; + float _LinearToGamma; + float _VATIncludesNormals; + float _AffectsShadows; + float _Frame; + float _Frames; + float _FrameInterpolation; + float _Loop; + float _InterpolateLoop; + float _Autoplay; + float _AutoplaySpeed; + + half _ParallaxMapping_Intensity; + half4 _ParallaxMapping_Map_ST; + half4 _ParallaxMapping_Vec; + half _WorldSpaceUVModeSelector; + half _ObjectSpaceUVModeSelector; + + uint _W9ParticleShaderFlags; + + uint _W9ParticleShaderFlags1; + + uint _W9ParticleShaderWrapFlags; + + uint _W9ParticleCustomDataFlag0; + uint _W9ParticleCustomDataFlag1; + uint _W9ParticleCustomDataFlag2; + uint _W9ParticleCustomDataFlag3; + + uint _UVModeFlag0; + uint _UVModeFlagType0; + + + uint _W9ParticleShaderColorChannelFlag; + uint _W9ParticleShaderPNoiseBlendFlag; + half _ProgramNoiseBaseBlendOpacity; + half _MaskPNoiseBlendOpacity; + half _DissolvePNoiseBlendOpacity; + half _DistortPNoiseBlendOpacity; + float4x4 _CustomLocalTransformLocalToWorld; + float4x4 _CustomLocalTransformWorldToLocal; + + CBUFFER_END + + #define NB_SHADER_FLAGS _W9ParticleShaderFlags + #define NB_SHADER_FLAGS1 _W9ParticleShaderFlags1 + #define NB_SHADER_WRAP_FLAGS _W9ParticleShaderWrapFlags + #define NB_SHADER_COLOR_CHANNEL_FLAG _W9ParticleShaderColorChannelFlag + #define NB_SHADER_PNOISE_BLEND_FLAG _W9ParticleShaderPNoiseBlendFlag + #define NB_CUSTOM_DATA_FLAG_0 _W9ParticleCustomDataFlag0 + #define NB_CUSTOM_DATA_FLAG_1 _W9ParticleCustomDataFlag1 + #define NB_CUSTOM_DATA_FLAG_2 _W9ParticleCustomDataFlag2 + #define NB_CUSTOM_DATA_FLAG_3 _W9ParticleCustomDataFlag3 + + float3x3 GetCustomLocalToWorld3x3() + { + return (float3x3)_CustomLocalTransformLocalToWorld; + } + + float3x3 GetCustomWorldToLocal3x3() + { + return (float3x3)_CustomLocalTransformWorldToLocal; + } + + float3 TransformWorldToObject_NB(float3 positionWS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return mul(_CustomLocalTransformWorldToLocal, float4(positionWS, 1.0)).xyz; + #else + return mul(unity_WorldToObject, float4(positionWS, 1.0)).xyz; + #endif + } + + float3 TransformObjectToWorld_NB(float3 positionOS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return mul(_CustomLocalTransformLocalToWorld, float4(positionOS, 1.0)).xyz; + #else + return mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz; + #endif + } + + float4 TransformObjectToHClip_NB(float3 positionOS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return TransformWorldToHClip(TransformObjectToWorld_NB(positionOS)); + #else + return TransformObjectToHClip(positionOS); + #endif + } + + float3 TransformWorldToObjectDir_NB(float3 dirWS, bool doNormalize = true) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + float3 dirOS = mul(GetCustomWorldToLocal3x3(), dirWS); + return doNormalize ? SafeNormalize(dirOS) : dirOS; + #else + float3 dirOS = mul((float3x3)unity_WorldToObject, dirWS); + return doNormalize ? SafeNormalize(dirOS) : dirOS; + #endif + } + + float3 TransformWorldToObjectNormal_NB(float3 normalWS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return SafeNormalize(mul(normalWS, GetCustomLocalToWorld3x3())); + #else + return SafeNormalize(mul(normalWS, (float3x3)unity_ObjectToWorld)); + #endif + } + + float3 TransformObjectToWorldDir_NB(float3 dirOS, bool doNormalize = true) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + float3 dirWS = mul(GetCustomLocalToWorld3x3(), dirOS); + return doNormalize ? SafeNormalize(dirWS) : dirWS; + #else + return TransformObjectToWorldDir(dirOS, doNormalize); + #endif + } + + float3 TransformObjectToWorldNormal_NB(float3 normalOS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return SafeNormalize(mul(normalOS, GetCustomWorldToLocal3x3())); + #else + return TransformObjectToWorldNormal(normalOS); + #endif + } + + real3 NBTransformWorldToTangentDir(real3 dirWS, real3x3 tangentToWorld, bool doNormalize = false) + { + // Unity 2021 / URP 12 does not expose TransformWorldToTangentDir. + real3 result = mul(tangentToWorld, dirWS); + return doNormalize ? SafeNormalize(result) : result; + } + + float3 GetCustomLocalSpaceNormalizeViewDir(float3 positionOS) + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + float3 viewDir = TransformWorldToObject_NB(_WorldSpaceCameraPos) - positionOS; + return SafeNormalize(viewDir); + #else + return GetObjectSpaceNormalizeViewDir(positionOS); + #endif + } + + float GetCustomLocalOddNegativeScale() + { + #ifdef _CUSTOM_LOCAL_TRANSFORM + return determinant(GetCustomLocalToWorld3x3()) < 0.0 ? -1.0 : 1.0; + #else + return GetOddNegativeScale(); + #endif + } + + + bool CheckLocalFlags(uint bits) + { + return (_W9ParticleShaderFlags&bits) != 0; + } + bool CheckLocalFlags1(uint bits) + { + return (_W9ParticleShaderFlags1&bits) != 0; + } + int CheckLocalWrapFlags(uint bits) + { + bool bit0 = (_W9ParticleShaderWrapFlags&bits) != 0; + bool bit1 = (_W9ParticleShaderWrapFlags&(bits<<16)) != 0; + if(!bit0 && !bit1) + { + return 0; + } + else if(bit0 && !bit1) + { + return 1; + } + else if(!bit0 && bit1) + { + return 2; + } + else if(bit0 && bit1) + { + return 3; + } + else + { + return -1; + } + } + + + SamplerState sampler_linear_repeat; + SamplerState sampler_linear_clamp; + SamplerState sampler_linear_RepeatU_ClampV; + SamplerState sampler_linear_ClampU_RepeatV; + SamplerState sampler_point_clamp; + + + + half4 SampleTexture2D(Texture2D tex,float2 uv,SAMPLER( textureSampler),bool sampleLOD = false,int lod = 0) + { + if (sampleLOD) + { + return SAMPLE_TEXTURE2D_LOD(tex,textureSampler,uv,lod); + + } + else + { + return SAMPLE_TEXTURE2D(tex,textureSampler,uv); + } + } + + + half4 SampleTexture2DWithWrapFlags(Texture2D tex,float2 uv,uint bits,bool sampleLOD = false,int lod = 0) + { + #ifdef _CAMERA_OPAQUE_DISTORT_PASS + int wrapMode; + if (bits == FLAG_BIT_WRAPMODE_BASEMAP) + { + wrapMode = 1; + } + else + { + wrapMode = CheckLocalWrapFlags(bits); + } + + #else + const int wrapMode = CheckLocalWrapFlags(bits); + #endif + + + #if defined(SHADER_TARGET_GLSL) ||defined (SHADER_API_GLES)|| defined(SHADER_API_GLES3) + switch (wrapMode) + { + case 0: uv = frac(uv);break; + case 1: uv = saturate(uv);break; + case 2: uv = float2(frac(uv.x),saturate(uv.y));break; + case 3: uv = float2(saturate(uv.x),frac(uv.y));break; + } + if (sampleLOD) + { + return SAMPLE_TEXTURE2D_LOD(tex,sampler_linear_clamp,uv,lod);//SamplerWillIgnore;需要在GLSL相关平台打包时强制设置为Clamp循环。 + + } + else + { + return SAMPLE_TEXTURE2D(tex,sampler_linear_clamp,uv);//SamplerWillIgnore;需要在GLSL相关平台打包时强制设置为Clamp循环。 + } + + #else + + switch (wrapMode) + { + case 0: + return SampleTexture2D(tex,uv,sampler_linear_repeat,sampleLOD,lod); + break; + case 1: + return SampleTexture2D(tex,uv,sampler_linear_clamp,sampleLOD,lod); + case 2: + return SampleTexture2D(tex,uv,sampler_linear_RepeatU_ClampV,sampleLOD,lod); + break; + case 3: + return SampleTexture2D(tex,uv,sampler_linear_ClampU_RepeatV,sampleLOD,lod); + break; + default: + return SampleTexture2D(tex,uv,sampler_linear_repeat,sampleLOD,lod); + break; + } + #endif + } + + half GetColorChannel(half4 color, int bitPos) + { + uint bits = _W9ParticleShaderColorChannelFlag >> bitPos; + bits = bits & 3; + if (bits == 0) return color.x; + if (bits == 1) return color.y; + if (bits == 2) return color.z; + return color.w; + } + + samplerCUBE _FresnelHDRITex; + sampler2D _MainTex; + + + + #define SOFT_PARTICLE_NEAR_FADE _SoftParticleFadeParams.x //�궨��SOFT_PARTICLE_NEAR_FADE ��Ϊ_SoftParticleFadeParams���Ե�x����~ + #define SOFT_PARTICLE_INV_FADE_DISTANCE _SoftParticleFadeParams.y + + #define CAMERA_NEAR_FADE _CameraFadeParams.x + #define CAMERA_INV_FADE_DISTANCE _CameraFadeParams.y + + Texture2D _BaseMap; + Texture2D _NoiseMap; + Texture2D _NoiseMaskMap; + Texture2D _EmissionMap; + Texture2D _MaskMap; + Texture2D _MaskMap2; + Texture2D _MaskMap3; + #ifdef _NORMALMAP + Texture2D _BumpTex; + #endif + + #ifdef _FX_LIGHT_MODE_SIX_WAY + Texture2D _RigRTBk; + Texture2D _RigLBtF; + Texture2D _SixWayEmissionRamp; + #endif + + #ifdef _CAMERA_OPAQUE_DISTORT_PASS + Texture2D _CameraOpaqueTexture; + #endif + + #ifdef _MATCAP + Texture2D _MatCapTex; + #endif + + // Pre-multiplied alpha helper + #if defined(_ALPHAPREMULTIPLY_ON) //if( blend: One OneMinusSrcAlpha) + #define ALBEDO_MUL albedo + #else + #define ALBEDO_MUL albedo.a + #endif + + + #ifdef SOFT_UI_FRAME + sampler2D _SoftUIFrameMask; + // half4 LB_RT; + #endif + + #ifdef _DISSOLVE + Texture2D _DissolveMap; + Texture2D _DissolveMaskMap; + Texture2D _DissolveRampMap; + #endif + + # ifdef _COLORMAPBLEND + Texture2D _ColorBlendMap; + #endif + + #ifdef _COLOR_RAMP + Texture2D _RampColorMap; + #endif + + Texture2D _VATTex; + float4 _VATTex_TexelSize; + + + + half4 tex2D_TryLinearizeWithoutAlphaFX(sampler2D tex, float2 uv) + { + half4 outColor = 0; + + #if defined(PARTICLE)//UI下使用ParticleBase不需要做 Gamma2Linear 转换 + UNITY_FLATTEN + if(CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON)) + { + outColor = tex2D(tex, uv); + } + else + { + outColor = TryLinearizeWithoutAlpha(tex2D(tex, uv)); + } + #endif + return outColor; + } + // + // Color blending fragment function + float4 MixParticleColor(float4 baseColor, float4 particleColor, float4 colorAddSubDiff) + { + #if defined(_COLOROVERLAY_ON) // Overlay blend + float4 output = baseColor; + output.rgb = lerp(1 - 2 * (1 - baseColor.rgb) * (1 - particleColor.rgb), 2 * baseColor.rgb * particleColor.rgb, step(baseColor.rgb, 0.5)); + output.a *= particleColor.a; + return output; + #elif defined(_COLORCOLOR_ON) // Color blend + half3 aHSL = RgbToHsv(baseColor.rgb); + half3 bHSL = RgbToHsv(particleColor.rgb); + half3 rHSL = half3(bHSL.x, bHSL.y, aHSL.z); + return half4(HsvToRgb(rHSL), baseColor.a * particleColor.a); + #elif defined(_COLORADDSUBDIFF_ON) // Additive, Subtractive and Difference blends based on 'colorAddSubDiff' + float4 output = baseColor; + output.rgb = baseColor.rgb + particleColor.rgb * colorAddSubDiff.x; + output.rgb = lerp(output.rgb, abs(output.rgb), colorAddSubDiff.y); + output.a *= particleColor.a; + return output; + #else // Default to Multiply blend + return baseColor * particleColor; + #endif + } + + // Soft particles - returns alpha value for fading particles based on the depth to the background pixel + float SoftParticles(float near, float far, float sceneZ,float thisZ) + { + float fade = 1; + if (near > 0.0 || far > 0.0) + { + // fade = saturate(far * ((sceneZ - near) - thisZ)); + float dist = sceneZ - thisZ; + fade = NB_Remap(dist, near,far,0,1); + } + return fade; + } + + + // Camera fade - returns alpha value for fading particles based on camera distance + half CameraFade(float near, float far, float thisZ) + { + return saturate((thisZ - near) * far); + } + + //相交位置渐变功能 + half4 Intersect(float IntersectRadius,half4 IntersectColor,float sceneZ,float thisZ) + { + half fade = sceneZ - thisZ; + fade =1- NB_Remap(fade,0,IntersectRadius,0,1); + + half4 c = 0; + c.rgb = IntersectColor.rgb; + c.a = fade*IntersectColor.a; + + return c; + } + + //遮挡穿透显示功能。 + half OccludeOpacity(half preAlpha,half _OccludeOpacity,half sceneZ,half thisZ) + { + half fakeZtest = step(thisZ,sceneZ); + return lerp(preAlpha*_OccludeOpacity,preAlpha,fakeZtest); + } + + + // Sample a texture and do blending for texture sheet animation if needed + half4 BlendTexture(sampler2D _Texture, float2 uv, float3 blendUv) + { + half4 color = tex2D_TryLinearizeWithoutAlphaFX(_Texture, uv); + + half4 color2; + #ifdef _FLIPBOOKBLENDING_ON + color2 = tex2D_TryLinearizeWithoutAlphaFX(_Texture, blendUv.xy); + color = lerp(color, color2, blendUv.z); + #endif + + // if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) + // { + // color2 = tex2D_TryLinearizeWithoutAlphaFX(_Texture, blendUv.xy); + // color = lerp(color, color2, blendUv.z); + // } + return color; + } + + half4 BlendTexture(Texture2D _Texture, float2 uv, float3 blendUv,uint bits) + { + half4 color = SampleTexture2DWithWrapFlags(_Texture,uv,bits); + half4 color2; + #ifdef _FLIPBOOKBLENDING_ON + color2 = SampleTexture2DWithWrapFlags(_Texture,blendUv.xy,bits); + color = lerp(color, color2, blendUv.z); + #endif + + // if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) + // { + // color2 = SampleTexture2DWithWrapFlags(_Texture, blendUv.xy,bits); + // color = lerp(color, color2, blendUv.z); + // } + return color; + } + + float2 UVOffsetAnimaiton(float2 UV,half2 OffsetSpeed) + { + float2 newUV = float2(OffsetSpeed.x*time+UV.x,OffsetSpeed.y*time+UV.y); + return newUV; + } + + // 采样噪波 + half4 SampleNoise(half4 NoiseOffset, Texture2D _Texture,float2 UV, half3 wordPos) + { + + float2 UV2 = float2(NoiseOffset.x * time + UV.x, NoiseOffset.y * time + UV.y); //_Time.y + + half4 color = SampleTexture2DWithWrapFlags(_Texture, UV2 ,FLAG_BIT_WRAPMODE_NOISEMAP); + // color.xy *= color.a; + + return color; + } + + + // // 替换颜色 + // half3 ReplaceColor_float(float3 In, float3 From, float3 To, float Range, float Fuzziness) + // { + // float Distance = distance(From, In); + // half3 Out = lerp(To, In, saturate((Distance - Range) / max(Fuzziness, 0.001))); //e-f? 0.00001 + // return Out; + // } + + //漩涡 圆形区域内变形。圆圈中心处的像素会旋转指定角度;圆圈中其他像素的旋转会随着相对于中心距离的变化而减小,在圆圈边缘处减小为零 + float2 UTwirl(float2 UV, float2 Center, float Strength) + { + float2 delta = UV - Center; + float angle = Strength * length(delta); + float x = cos(angle) * delta.x - sin(angle) * delta.y; + float y = sin(angle) * delta.x + cos(angle) * delta.y; + return float2(x + Center.x , y + Center.y ); + + } + + //Fresnel + half4 Unity_FresnelEffect(float3 Normal, float3 ViewDir, float Power, float Dire,half fresnelPos) + { + // half aa = saturate(dot(normalize(Normal), (ViewDir))); + half aa = dot(normalize(Normal), (ViewDir)); + aa = (aa+1)*0.5; + aa = NB_Remap(aa,fresnelPos,1,0,1); + aa = lerp(aa, (1 - aa), Dire); + half Out = pow( aa, Power); + return Out; + } + + half3 Rotation(half3 normalizedDirection,half3 rotation) + { + half4 Dir = half4(normalizedDirection,1); + float4x4 M_RotationX = float4x4( + + 1,0,0,0, + 0,cos(rotation.x),sin(rotation.x),0, + 0,-sin(rotation.x),cos(rotation.x),0, + 0,0,0,1 + + ); + float4x4 M_RotationY = float4x4( + + cos(rotation.y),0,sin(rotation.y),0, + 0,1,0,0, + -sin(rotation.y),0,cos(rotation.y),0, + 0,0,0,1 + + ); + float4x4 M_RotationZ = float4x4( + + cos(rotation.z),sin(rotation.z),0,0, + -sin(rotation.z),cos(rotation.z),0,0, + 0,0,1,0, + 0,0,0,1 + + ); + + return mul(M_RotationZ,mul(M_RotationY,mul(M_RotationX,Dir))); + + } + + //----------------公告板功能-----------------// + half3 BillBoard(float3 camPos, float3 vertexPos, int billboardType, int _ReverseZ) + { + float3 Z = normalize(mul(unity_WorldToObject, float4(_WorldSpaceCameraPos,1))); + if(_ReverseZ == 1) + { + Z *= -1; + } + Z.y *= billboardType; + + float3 Y = float3(0,1,0); + float3 X = normalize(cross(Z,Y)); + Y = normalize(cross(X,Z)); + float4x4 M = float4x4( + X.x, Y.x, Z.x, 0, + X.y, Y.y, Z.y, 0, + X.z, Y.z, Z.z, 0, + 0,0,0,1 + ); + float3 newPos = mul(M, vertexPos); + return newPos; + } + + half3 BillBoardNormal(float3 camPos, float3 vertexPos, int billboardType, int _ReverseZ) + { + float3 Z = normalize(mul(unity_WorldToObject, float4(_WorldSpaceCameraPos,1))); + if(_ReverseZ == 1) + { + Z *= -1; + } + Z.y *= billboardType; + + float3 Y = float3(0,1,0); + float3 X = normalize(cross(Y,Z)); + Y = normalize(cross(X,Z)); + float4x4 M = float4x4( + X.x, Y.x, Z.x, 0, + X.y, Y.y, Z.y, 0, + X.z, Y.z, Z.z, 0, + 0,0,0,1 + ); + float3 newPos = -mul(M, vertexPos); + return newPos; + } + + + float2 ParticleUVCommonProcess(float2 originUVAfterTwirlPolar,float4 scaleTilling,float2 offset = float2(0,0),float rotation = 0,float2 rotationCenter = float2(0.5,0.5)) + { + float2 uv = originUVAfterTwirlPolar; + uv = Rotate_Radians_float(uv,rotationCenter,rotation); + uv = uv*scaleTilling.xy + scaleTilling.zw; + + uv = UVOffsetAnimaiton(uv,offset); + + return uv; + } + + struct ParticleUVs + { + float2 mainTexUV; + float2 specUV; + float2 animBlendUV; + float2 maskMapUV; + float2 maskMap2UV; + float2 maskMap3UV; + float2 emissionUV; + float2 dissolve_uv; + float2 dissolve_mask_uv; + float2 dissolve_noise1_UV; + float2 dissolve_noise2_UV; + float2 colorBlendUV; + float2 noiseMapUV; + float2 noiseMaskMapUV; + float2 bumpTexUV; + float2 colorRampMapUV; + float2 sharedUV; + }; + + float2 getPosUVByPosUVMode(float3 pos,half posUVMode) + { + switch ((int)posUVMode) + { + case 0: + return pos.xy; + case 1: + return pos.xz; + case 2: + return pos.yz; + default: + return pos.xz; + } + } + + BaseUVs ProcessBaseUVs(float4 meshTexcoord0, float2 specialUVInTexcoord3,float4 VaryingsP_Custom1,float4 VaryingsP_Custom2,float3 postionOS,float3 positionWS,float2 screenUV) + { + //UV2的内容在外边就决定好。 + float2 defaultUVChannel = meshTexcoord0.xy; + float2 specialUVChannel = meshTexcoord0.zw; + #if _FLIPBOOKBLENDING_ON + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) & CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)) + { + specialUVChannel = specialUVInTexcoord3; + } + #else + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UV_FROM_MESH)) + { + //Mesh条件下开启使用特殊UV通道的情况 + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD1)) + { + specialUVChannel = VaryingsP_Custom1.xy; + } + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_USE_TEXCOORD2)) + { + specialUVChannel = VaryingsP_Custom2.xy; + } + } + else + { + //只有在粒子系统下开启特殊通道的情况,会在面板层引导合并相关内容。UI/Mesh不开启特殊通道没有意义。 + specialUVChannel = meshTexcoord0.zw; + } + #endif + + + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE)) + { + defaultUVChannel = defaultUVChannel*_MainTex_Reverse_ST.xy +_MainTex_Reverse_ST.zw; + } + //TODO:补写MeshUV的实现 + float2 cylinderUV = meshTexcoord0.xy; + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_CYLINDER_CORDINATE)) + { + float4x4 _CylinderUVMatrix = float4x4(_CylinderMatrix0,_CylinderMatrix1,_CylinderMatrix2,_CylinderMatrix3); + postionOS = mul(_CylinderUVMatrix,float4(postionOS,1)); + cylinderUV = CylinderCoordinate(postionOS); + } + + float2 UVAfterTwirlPolar = defaultUVChannel; + if(CheckLocalFlags(FLAG_BIT_PARTICLE_UTWIRL_ON)) + { + UVAfterTwirlPolar = UTwirl(defaultUVChannel,_TWParameter.xy, _TWStrength); + } + if(CheckLocalFlags(FLAG_BIT_PARTICLE_POLARCOORDINATES_ON)) + { + float2 UVAfterTwirl = UVAfterTwirlPolar; + UVAfterTwirlPolar = PolarCoordinates(UVAfterTwirlPolar,_PCCenter.xy); + UVAfterTwirlPolar = lerp(UVAfterTwirl,UVAfterTwirlPolar,_PCCenter.z); + } + BaseUVs baseUVs = (BaseUVs)0; + baseUVs.defaultUVChannel = defaultUVChannel; + baseUVs.specialUVChannel = specialUVChannel; + baseUVs.uvAfterTwirlPolar = UVAfterTwirlPolar; + baseUVs.cylinderUV = cylinderUV; + + baseUVs.screenUV = screenUV; + baseUVs.worldPosUV = getPosUVByPosUVMode(positionWS,_WorldSpaceUVModeSelector); + baseUVs.objectPosUV = getPosUVByPosUVMode(postionOS,_ObjectSpaceUVModeSelector); + + baseUVs.sharedUV = defaultUVChannel; + float2 sharedUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_SHAREDUV,baseUVs); + _SharedUV_Vec.z += time * _SharedUV_Vec.w; + sharedUV = Rotate_Radians_float(sharedUV, half2(0.5, 0.5), _SharedUV_Vec.z); //主贴图旋转 + + sharedUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + sharedUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + sharedUV = sharedUV *_SharedUV_ST.xy +_SharedUV_ST.zw ; //主帖图UV重复和偏移 + + sharedUV = UVOffsetAnimaiton(sharedUV,_SharedUV_Vec.xy); + baseUVs.sharedUV = sharedUV; + + baseUVs.mainTexUV = defaultUVChannel; + float2 baseMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MAINTEX,baseUVs); + + float2 mainTexUV = 0; + _BaseMapUVRotation += time * _BaseMapUVRotationSpeed; + baseMapUV = Rotate_Radians_float(baseMapUV, half2(0.5, 0.5), _BaseMapUVRotation); //主贴图旋转 + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_UIEFFECT_ON) & !CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_BASEMAP_MODE)) + { + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_UIEFFECT_SPRITE_MODE)) + { + float2 originUV = meshTexcoord0.xy;//精灵主贴图不调整。 + mainTexUV = originUV*_UI_MainTex_ST.xy+_UI_MainTex_ST.zw; + } + else + { + mainTexUV = baseMapUV*_UI_MainTex_ST.xy+_UI_MainTex_ST.zw; + } + } + else + { + baseMapUV.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + baseMapUV.y += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + mainTexUV = TRANSFORM_TEX(baseMapUV, _BaseMap); //主帖图UV重复和偏移 + } + mainTexUV = UVOffsetAnimaiton(mainTexUV,_BaseMapMaskMapOffset.xy); + baseUVs.mainTexUV = mainTexUV; + + return baseUVs; + } + + + void ParticleProcessUV(inout ParticleUVs particleUVs,float4 meshTexcoord0,float4 VaryingsP_Custom1,float4 VaryingsP_Custom2,BaseUVs baseUVs) + { + particleUVs.specUV = baseUVs.specialUVChannel; + + particleUVs.mainTexUV = baseUVs.mainTexUV; + //------------------------------------------------- + #ifdef _FLIPBOOKBLENDING_ON //开启序列帧融合 + if(CheckLocalFlags1(FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER)) + { + // float2 baseMapUV = (baseUVs.mainTexUV - _BaseMap_ST.zw)/_BaseMap_ST.xy; + //走AnimationSheetHelper脚本的情况,永远和baseMap同步。 + particleUVs.animBlendUV = meshTexcoord0.xy*_BaseMap_AnimationSheetBlend_ST.xy+_BaseMap_AnimationSheetBlend_ST.zw; + } + else + { + //走粒子的情况 + particleUVs.animBlendUV = meshTexcoord0.zw; + } + #endif + + + #if defined(_NORMALMAP) + float2 bumpTexUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_BUMPTEX,baseUVs); + bumpTexUV = TRANSFORM_TEX(bumpTexUV, _BumpTex); + particleUVs.bumpTexUV = bumpTexUV; + + #endif + + + + #if defined(_MASKMAP_ON) + + float2 MaskMapuv = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP,baseUVs); + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON)) + { + _MaskMapUVRotation += time * _MaskMapRotationSpeed; + } + + MaskMapuv= Rotate_Radians_float(MaskMapuv, half2(0.5, 0.5), _MaskMapUVRotation); + + MaskMapuv = TRANSFORM_TEX(MaskMapuv, _MaskMap); + + MaskMapuv.x += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + MaskMapuv.y += GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + + MaskMapuv = UVOffsetAnimaiton(MaskMapuv,_MaskMapOffsetAnition.xy); + particleUVs.maskMapUV = MaskMapuv; + + #if defined(_MASKMAP2_ON) + { + float2 maskMap2UV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP_2,baseUVs); + maskMap2UV = Rotate_Radians_float(maskMap2UV,half2(0.5,0.5),_MaskMapVec.y); + maskMap2UV = maskMap2UV * _MaskMap2_ST.xy + _MaskMap2_ST.zw; + + maskMap2UV = UVOffsetAnimaiton(maskMap2UV,_MaskMapOffsetAnition.zw); + particleUVs.maskMap2UV = maskMap2UV; + } + #endif + + #if defined(_MASKMAP3_ON) + { + float2 maskMap3UV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_MASKMAP_3,baseUVs); + maskMap3UV = Rotate_Radians_float(maskMap3UV,half2(0.5,0.5),_MaskMapVec.z); + + maskMap3UV = maskMap3UV* _MaskMap3_ST.xy + _MaskMap3_ST.zw; + + maskMap3UV = UVOffsetAnimaiton(maskMap3UV,_MaskMap3OffsetAnition.xy); + particleUVs.maskMap3UV = maskMap3UV; + } + #endif + + #endif + + + #if defined(_EMISSION) + float2 emissionUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_EMISSION_MAP,baseUVs); + emissionUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + emissionUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + particleUVs.emissionUV = ParticleUVCommonProcess(emissionUV,_EmissionMap_ST,_EmissionMapUVOffset.xy,_EmissionMapUVRotation); + #endif + + #if defined(_DISSOLVE) + _DissolveMap_ST.z += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + _DissolveMap_ST.w += GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + + float2 dissolveUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP,baseUVs); + particleUVs.dissolve_uv = ParticleUVCommonProcess(dissolveUV,_DissolveMap_ST,_DissolveOffsetRotateDistort.xy,_DissolveOffsetRotateDistort.z); + #if defined(_DISSOLVE_MASK) + { + float2 dissolveMaskUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP,baseUVs); + particleUVs.dissolve_mask_uv = ParticleUVCommonProcess(dissolveMaskUV,_DissolveMaskMap_ST,float2(0,0),_DissolveOffsetRotateDistort.z); + } + #endif + #endif + + #ifdef _PROGRAM_NOISE_ACTIVE + float2 programNoiseUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE,baseUVs); + programNoiseUV = Rotate_Radians_float(programNoiseUV,half2(0.5,0.5),_ProgramNoise_Rotate); + #if defined(_PROGRAM_NOISE_SIMPLE) + { + _DissolveVoronoi_Vec4.x += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + _DissolveVoronoi_Vec4.y += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + particleUVs.dissolve_noise1_UV = programNoiseUV * _DissolveVoronoi_Vec.xy + _DissolveVoronoi_Vec4.xy + time*_DissolveVoronoi_Vec3.xy; + + } + #endif + #if defined(_PROGRAM_NOISE_VORONOI) + { + _DissolveVoronoi_Vec4.z += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + _DissolveVoronoi_Vec4.w += GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + particleUVs.dissolve_noise2_UV = programNoiseUV * _DissolveVoronoi_Vec.zw + _DissolveVoronoi_Vec4.zw + time*_DissolveVoronoi_Vec3.zw; + } + #endif + #endif + + + #ifdef _COLORMAPBLEND + float2 colorBlendUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP,baseUVs); + colorBlendUV.x += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X,0,VaryingsP_Custom1,VaryingsP_Custom2); + colorBlendUV.y += GetCustomData(_W9ParticleCustomDataFlag3,FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y,0,VaryingsP_Custom1,VaryingsP_Custom2); + particleUVs.colorBlendUV = ParticleUVCommonProcess(colorBlendUV,_ColorBlendMap_ST,_ColorBlendMapOffset.xy,_ColorBlendVec.w); + + #endif + #ifdef _COLOR_RAMP + float2 colorRampMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP,baseUVs); + particleUVs.colorRampMapUV = ParticleUVCommonProcess(colorRampMapUV,_RampColorMap_ST,_RampColorMapOffset.xy,_RampColorMapOffset.w); + #endif + half cum_noise = 0; + + //TODO + + #if defined(_NOISEMAP) + + //和ParticleUVCommonProcess相比,此处没有UV动画,NoiseMap的UV流动在最终的SampleNoise中进行 + float2 noiseMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_NOISE_MAP,baseUVs); + particleUVs.noiseMapUV = ParticleUVCommonProcess(noiseMapUV,_NoiseMap_ST,half2(0,0),_NoiseMapUVRotation); + + #if defined(_NOISE_MASKMAP) + { + float2 noiseMaskMapUV = GetUVByUVMode(_UVModeFlag0,_UVModeFlagType0,FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP,baseUVs); + particleUVs.noiseMaskMapUV = ParticleUVCommonProcess(noiseMaskMapUV,_NoiseMaskMap_ST,half2(0,0),0); + + } + #endif + #endif + + + + } + + #if defined(_VERTEX_OFFSET) + Texture2D _VertexOffset_Map; + #if defined(_VERTEX_OFFSET_MASKMAP) + Texture2D _VertexOffset_MaskMap; + #endif + + // half3 _VertexOffset_Vec; + // half3 _VertexOffset_CustomDir; + // half4 _VertexOffset_Map_ST; + + half3 VetexOffset(half3 positionOS,half2 originUV,half2 originMaskUV,half3 normalOS,out half3 offsetOS) + { + half2 uv = TRANSFORM_TEX(originUV,_VertexOffset_Map); + uv = UVOffsetAnimaiton(uv,_VertexOffset_Vec.xy); + // half vertexOffsetSample = tex2Dlod(_VertexOffset_Map,half4(uv,0,0)); + half vertexOffsetSample = SampleTexture2DWithWrapFlags(_VertexOffset_Map,uv,FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP,true,0); + // UNITY_BRANCH + // if(CheckLocalWrapFlags(FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP)) + // { + // vertexOffsetSample = SAMPLE_TEXTURE2D_LOD(_VertexOffset_Map,sampler_linear_clamp,uv,0); + // } + // else + // { + // vertexOffsetSample = SAMPLE_TEXTURE2D_LOD(_VertexOffset_Map,sampler_linear_repeat,uv,0); + // } + + if (!CheckLocalFlags1(FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO)) + { + vertexOffsetSample = vertexOffsetSample*2-1; + } + + half vertexOffsetMask = 1; + #if defined(_VERTEX_OFFSET_MASKMAP) + { + half2 maskUV = TRANSFORM_TEX(originMaskUV,_VertexOffset_MaskMap); + maskUV = UVOffsetAnimaiton(maskUV,_VertexOffset_MaskMap_Vec.xy); + half vertexOffsetMaskSample = SampleTexture2DWithWrapFlags(_VertexOffset_MaskMap,maskUV,FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP,true,0); + vertexOffsetMask = lerp(1,vertexOffsetMaskSample,_VertexOffset_MaskMap_Vec.z); + } + #endif + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR)) + { + offsetOS = normalOS*_VertexOffset_Vec.z*vertexOffsetSample*vertexOffsetMask; + } + else + { + offsetOS = _VertexOffset_CustomDir*_VertexOffset_Vec.z*vertexOffsetSample*vertexOffsetMask; + } + + return positionOS + offsetOS; + + } + #endif + + //向UV横向两边的色散。 + #if defined(_CHROMATIC_ABERRATION) + half4 DistortionChoraticaberrat(Texture2D baseTexture,half2 originUV, half2 uvAfterNoise,half ChoraticaberratIntensity,uint bits) + { + half2 delta = half2(originUV.x *2-1,0); + + if(CheckLocalFlags(FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE)) + { + half2 NoiseIntensity = uvAfterNoise - originUV; + // half noiseXIntensity = abs(NoiseIntensity.x); + // delta *= ChoraticaberratIntensity*noiseXIntensity; + delta = NoiseIntensity*ChoraticaberratIntensity*10; + } + else + { + delta *= ChoraticaberratIntensity; + } + + half2 ra = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise,bits).xw; + ra.r *= ra.y; + half2 ga = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise - delta,bits).yw; + ga.r *= ga.y; + half2 ba = SampleTexture2DWithWrapFlags(baseTexture,uvAfterNoise - delta*2,bits).zw; + ba.r *= ba.y; + return half4(ra.r,ga.r,ba.r,clamp(ra.y*0.5+ga.y*0.5+ba.y*0.5,0,1)); + } + #endif + + bool needSceneDepth() + { + #if defined(_DEPTH_DECAL) || defined(_SOFTPARTICLES_ON) || defined(_DEPTH_OUTLINE) + return true; + #endif + + return false; + } + + bool needEyeDepth() + { + #if defined(_SOFTPARTICLES_ON) || defined(_DEPTH_OUTLINE) || defined(_DISTANCE_FADE) + return true; + #endif + + return false; + } + + bool needPositionVS() + { + #if defined(_MATCAP) + return true; + #endif + + if (unity_OrthoParams.w == 1) + { + return true; + } + return false; + } + + bool ignoreFresnel() + { + #if defined(PARTICLE_BACKFACE_PASS) + return true; + #endif + return false; + } + + float3 CustomRefract(float3 incident, float3 normal, float eta) + { + float N_dot_I = dot(normal, incident); + float k = 1.0f - eta * eta * (1.0f - N_dot_I * N_dot_I); + + // 检查全内反射 + if (k < 0.0) + { + // 全内反射时返回零向量 + return float3(0, 0, 0); + } + else + { + // 计算折射方向 + return eta * incident - (eta * N_dot_I + sqrt(k)) * normal; + } + } + + Texture2D _ParallaxMapping_Map; + + half2 ParallaxMappingSimple(half2 texCoords, half3 viewDir) + { + float height = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,texCoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; + height *= _ParallaxMapping_Intensity; + viewDir = normalize(viewDir); + viewDir.xy /= (viewDir.z); + texCoords -= viewDir.xy * height; + return texCoords; + } + + half2 ParallaxMappingPeelDepth(half2 texCoords, half3 viewDir) + { + const float minLayers = 2; + const float maxLayers = 32; + float numLayers = lerp(maxLayers, minLayers, abs(dot(half3(0.0, 0.0, 1.0), viewDir)));//视线越垂直于表面,层数越少,反之越多。 + float layerDepth = 1/numLayers; + float currentLayerDepth = 0; + // viewDir.xy/=viewDir.z; + half2 p = viewDir.xy*_ParallaxMapping_Intensity; + half2 deltaTexcoord = p/numLayers; + + half2 currentTexcoords = texCoords; + float currentMapDepthValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,currentTexcoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; + + [loop] + while (currentLayerDepth < currentMapDepthValue ) + { + currentTexcoords -= deltaTexcoord; + currentMapDepthValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map,currentTexcoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; + currentLayerDepth += layerDepth; + } + + return currentTexcoords; + + } + float2 ParallaxOcclusionMapping(float2 texCoords, float3 viewDir) + { + texCoords = texCoords * _ParallaxMapping_Map_ST + _ParallaxMapping_Map_ST.zw; + // number of depth layers + // const float minLayers = 10; + // const float maxLayers = 10; + const float minLayers = _ParallaxMapping_Vec.x; + const float maxLayers = _ParallaxMapping_Vec.y; + float numLayers = lerp(maxLayers, minLayers, abs(dot(half3(0.0, 0.0, 1.0), viewDir))); + // calculate the size of each layer + float layerDepth = 1.0 / numLayers; + // depth of current layer + float currentLayerDepth = 0.0; + // the amount to shift the texture coordinates per layer (from vector P) + float2 P = viewDir.xy / viewDir.z * _ParallaxMapping_Intensity; + float2 deltaTexCoords = P / numLayers; + + // get initial values + float2 currentTexCoords = texCoords; + float currentDepthMapValue = SampleTexture2DWithWrapFlags(_ParallaxMapping_Map, currentTexCoords,FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP).r; + currentLayerDepth = clamp(currentLayerDepth,0,1); + + int i = 0; + [loop] + while(currentLayerDepth < currentDepthMapValue && i= timeArr[arrCount - 1]) { + // return int2(arrCount - 1, arrCount); // 大于等于最大值 + // } + + // 顺序查找第一个大于X的元素索引 + [unroll] + for (int i = 0; i < arrCount; i++) { + if (timeArr[i] > gradientTime) { + return int2(i - 1, i); // 返回区间索引 + } + } + return int2(-1, 0); // 理论上不会执行此处 + } + half GetGradientIndexInterval(half timeArr[6],int arrCount,int2 indexes,half gradientTime) + { + //超出范围的直接在外面就判断好。 + // half smallVal = indexes.x < 0 ? 0:timeArr[indexes.x]; + half smallVal = timeArr[indexes.x]; + // half bigVal = indexes.y >= arrCount ? 1 : timeArr[indexes.y]; + half bigVal = timeArr[indexes.y]; + return (gradientTime - smallVal) / (bigVal - smallVal); + } + + half3 GetGradientColorValue(half3 colorArr[6],half timeArr[6], int arrCount,half gradientTime) + { + if (gradientTime <= timeArr[0]) + { + return colorArr[0]; + } + else if (gradientTime >= timeArr[arrCount - 1] ) + { + return colorArr[arrCount - 1]; + } + else + { + int2 indexes = GetGradientIndex(timeArr, arrCount, gradientTime); + half interval = GetGradientIndexInterval(timeArr, arrCount, indexes, gradientTime); + interval = SmoothStep01(interval); + return lerp(colorArr[indexes.x], colorArr[indexes.y], interval); + } + } + + half GetGradientAlphaValue(half alphaArr[6],half timeArr[6], int arrCount,half gradientTime) + { + if (gradientTime <= timeArr[0]) + { + return alphaArr[0]; + } + else if (gradientTime >= timeArr[arrCount - 1] ) + { + return alphaArr[arrCount - 1]; + } + else + { + int2 indexes = GetGradientIndex(timeArr, arrCount, gradientTime); + half interval = GetGradientIndexInterval(timeArr, arrCount, indexes, gradientTime); + interval = SmoothStep01(interval);//TODO:消耗很大,如何避免? + half alpha = lerp(alphaArr[indexes.x], alphaArr[indexes.y], interval); + alpha *= alpha;//Make Alpha Smoother + return alpha ; + } + } + + half3 GetPackedGradientColorKey(half4 key0, half4 key1, half4 key2, half4 key3, half4 key4, half4 key5, int index) + { + if (index <= 0) return key0.rgb; + if (index == 1) return key1.rgb; + if (index == 2) return key2.rgb; + if (index == 3) return key3.rgb; + if (index == 4) return key4.rgb; + return key5.rgb; + } + + half GetPackedGradientColorTime(half4 key0, half4 key1, half4 key2, half4 key3, half4 key4, half4 key5, int index) + { + if (index <= 0) return key0.a; + if (index == 1) return key1.a; + if (index == 2) return key2.a; + if (index == 3) return key3.a; + if (index == 4) return key4.a; + return key5.a; + } + + half GetPackedGradientAlphaKey(half4 pack0, half4 pack1, half4 pack2, int index) + { + if (index <= 0) return pack0.x; + if (index == 1) return pack0.z; + if (index == 2) return pack1.x; + if (index == 3) return pack1.z; + if (index == 4) return pack2.x; + return pack2.z; + } + + half GetPackedGradientAlphaTime(half4 pack0, half4 pack1, half4 pack2, int index) + { + if (index <= 0) return pack0.y; + if (index == 1) return pack0.w; + if (index == 2) return pack1.y; + if (index == 3) return pack1.w; + if (index == 4) return pack2.y; + return pack2.w; + } + + int2 GetPackedGradientColorIndex(half4 key0, half4 key1, half4 key2, half4 key3, half4 key4, half4 key5, int arrCount, half gradientTime) + { + int2 indexes = int2(-1, 0); + bool found = false; + [unroll] + for (int i = 0; i < 6; i++) + { + if (!found && i < arrCount && GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, i) > gradientTime) + { + indexes = int2(i - 1, i); + found = true; + } + } + return indexes; + } + + int2 GetPackedGradientAlphaIndex(half4 pack0, half4 pack1, half4 pack2, int arrCount, half gradientTime) + { + int2 indexes = int2(-1, 0); + bool found = false; + [unroll] + for (int i = 0; i < 6; i++) + { + if (!found && i < arrCount && GetPackedGradientAlphaTime(pack0, pack1, pack2, i) > gradientTime) + { + indexes = int2(i - 1, i); + found = true; + } + } + return indexes; + } + + half3 SamplePackedGradientColor(half4 key0, half4 key1, half4 key2, half4 key3, half4 key4, half4 key5, int arrCount, half gradientTime) + { + if (gradientTime <= GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, 0)) + { + return GetPackedGradientColorKey(key0, key1, key2, key3, key4, key5, 0); + } + else if (gradientTime >= GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, arrCount - 1)) + { + return GetPackedGradientColorKey(key0, key1, key2, key3, key4, key5, arrCount - 1); + } + else + { + int2 indexes = GetPackedGradientColorIndex(key0, key1, key2, key3, key4, key5, arrCount, gradientTime); + half smallVal = GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, indexes.x); + half bigVal = GetPackedGradientColorTime(key0, key1, key2, key3, key4, key5, indexes.y); + half interval = SmoothStep01((gradientTime - smallVal) / (bigVal - smallVal)); + return lerp( + GetPackedGradientColorKey(key0, key1, key2, key3, key4, key5, indexes.x), + GetPackedGradientColorKey(key0, key1, key2, key3, key4, key5, indexes.y), + interval); + } + } + + half SamplePackedGradientAlpha(half4 pack0, half4 pack1, half4 pack2, int arrCount, half gradientTime) + { + if (gradientTime <= GetPackedGradientAlphaTime(pack0, pack1, pack2, 0)) + { + return GetPackedGradientAlphaKey(pack0, pack1, pack2, 0); + } + else if (gradientTime >= GetPackedGradientAlphaTime(pack0, pack1, pack2, arrCount - 1)) + { + return GetPackedGradientAlphaKey(pack0, pack1, pack2, arrCount - 1); + } + else + { + int2 indexes = GetPackedGradientAlphaIndex(pack0, pack1, pack2, arrCount, gradientTime); + half smallVal = GetPackedGradientAlphaTime(pack0, pack1, pack2, indexes.x); + half bigVal = GetPackedGradientAlphaTime(pack0, pack1, pack2, indexes.y); + half interval = SmoothStep01((gradientTime - smallVal) / (bigVal - smallVal)); + half alpha = lerp( + GetPackedGradientAlphaKey(pack0, pack1, pack2, indexes.x), + GetPackedGradientAlphaKey(pack0, pack1, pack2, indexes.y), + interval); + alpha *= alpha; + return alpha; + } + } + + void ColorAdjustment(inout half3 result,inout half alpha,half4 customData1,half4 customData2) + { + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_HUESHIFT_ON)) + { + half3 hsv = RgbToHsv(result); + _HueShift = GetCustomData(_W9ParticleCustomDataFlag0,FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT,_HueShift,customData1,customData2); + hsv.r += _HueShift; + result = HsvToRgb(hsv); + } + + UNITY_BRANCH + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST)) + { + _Contrast = GetCustomData(_W9ParticleCustomDataFlag2,FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST,_Contrast,customData1,customData2); + result.rgb = lerp(_ContrastMidColor,result.rgb,_Contrast); + } + + UNITY_BRANCH + if(CheckLocalFlags(FLAG_BIT_SATURABILITY_ON)) + { + half3 resultWB = luminance(result); + _Saturability = GetCustomData(_W9ParticleCustomDataFlag1,FLAGBIT_POS_1_CUSTOMDATA_SATURATE,_Saturability,customData1,customData2); + result.rgb = lerp(resultWB.rgb, result.rgb, _Saturability); + } + + + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE)) + { + half3 colorA = result.rgb*_BaseMapColorRefine.x; + half3 colorB = pow(result.rgb,_BaseMapColorRefine.y)*_BaseMapColorRefine.z; + result.rgb = lerp(colorA,colorB,_BaseMapColorRefine.w); + } + + if (CheckLocalFlags(FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA)) + { + result.rgb *= alpha; + } + + + } + +#endif diff --git a/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderInput.hlsl.meta b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderInput.hlsl.meta new file mode 100644 index 00000000..d7e7ce3c --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/HLSL/NBShaderInput.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0aaec9236001406ebcc710ac8f3f7c43 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/NBShaders2/Shader/NBShader.shader b/Packages/NB_FX/NBShaders2/Shader/NBShader.shader new file mode 100644 index 00000000..133c29e8 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/NBShader.shader @@ -0,0 +1,1336 @@ +Shader "Effects/NBShader" +//Shader "Effects/NBShader开发中" +{ + Properties + { + _BigBlockModeSettingFoldOut("_BigBlockModeSettingFoldOut",Float) = 0 + _BaseOptionBigBlockItemFoldOut("BaseOptionBigBlockItem",Float) = 0 + _MainTexBigBlockItemFoldOut("_MainTexBigBlockItemFoldOut",Float) = 0 + _LightBigBlockItemFoldOut("_LightBigBlockItemFoldOut",Float) = 0 + _FeatureBigBlockItemFoldOut("_FeatureBigBlockItemFoldOut",Float) = 0 + _TABigBlockItemFoldOut("_TABigBlockItemFoldOut",Float) = 0 + [HideInInspector] _NBShaderFeatureTier("NBShader Feature Tier", Float) = 3 + _BaseColorAdjustmentFoldOut("_BaseColorAdjustmentFoldOut",Float) = 0 + _HueShiftFoldOut("_HueShiftFoldOut",Float) = 0 + _SaturabilityFoldOut("_SaturabilityFoldOut",Float) = 0 + _ContrastFoldOut("_ContrastFoldOut",Float) = 0 + _BaseMapColorRefineFoldOut("_BaseMapColorRefineFoldOut",Float) = 0 + _BaseBackColorFoldOut("_BaseBackColorFoldOut",Float) = 0 + _DistanceFadeFoldOut("_DistanceFadeFoldOut",Float) = 0 + _SoftParticlesFoldOut("_SoftParticlesFoldOut",Float) = 0 + _BaseMapFoldOut("_BaseMapFoldOut",Float) = 0 + _MainTexUVModeFoldOut("_MainTexUVModeFoldOut",Float) = 0 + _GlobalTwirlFoldOut("_GlobalTwirlFoldOut",Float) = 0 + _GlobalPolarFoldOut("_GlobalPolarFoldOut",Float) = 0 + _BumpToggleFoldOut("_BumpToggleFoldOut",Float) = 0 + _BumpTexFoldOut("_BumpTexFoldOut",Float) = 0 + _BumpUVModeFoldOut("_BumpUVModeFoldOut",Float) = 0 + _MatCapFoldOut("_MatCapFoldOut",Float) = 0 + _MaskBlockFoldOut("_MaskBlockFoldOut",Float) = 0 + _MaskRefineFoldOut("_MaskRefineFoldOut",Float) = 0 + _MaskMapFoldOut("_MaskMapFoldOut",Float) = 0 + _MaskUVModeFoldOut("_MaskUVModeFoldOut",Float) = 0 + _MaskRotationFoldOut("_MaskRotationFoldOut",Float) = 0 + _Mask2BlockFoldOut("_Mask2BlockFoldOut",Float) = 0 + _Mask2UVModeFoldOut("_Mask2UVModeFoldOut",Float) = 0 + _Mask3BlockFoldOut("_Mask3BlockFoldOut",Float) = 0 + _Mask3UVModeFoldOut("_Mask3UVModeFoldOut",Float) = 0 + _NoiseBlockFoldOut("_NoiseBlockFoldOut",Float) = 0 + _ScreenDistortAlphaFoldOut("_ScreenDistortAlphaFoldOut",Float) = 0 + _NoiseMapFoldOut("_NoiseMapFoldOut",Float) = 0 + _NoiseUVModeFoldOut("_NoiseUVModeFoldOut",Float) = 0 + _NoiseMaskBlockFoldOut("_NoiseMaskBlockFoldOut",Float) = 0 + _NoiseMaskUVModeFoldOut("_NoiseMaskUVModeFoldOut",Float) = 0 + _ChromaticAberrationFoldOut("_ChromaticAberrationFoldOut",Float) = 0 + _EmissionBlockFoldOut("_EmissionBlockFoldOut",Float) = 0 + _EmissionUVModeFoldOut("_EmissionUVModeFoldOut",Float) = 0 + _ColorBlendBlockFoldOut("_ColorBlendBlockFoldOut",Float) = 0 + _ColorBlendUVModeFoldOut("_ColorBlendUVModeFoldOut",Float) = 0 + _RampColorBlockFoldOut("_RampColorBlockFoldOut",Float) = 0 + _RampColorUVModeFoldOut("_RampColorUVModeFoldOut",Float) = 0 + _DissolveBlockFoldOut("_DissolveBlockFoldOut",Float) = 0 + _DissolveMapFoldOut("_DissolveMapFoldOut",Float) = 0 + _DissolveUVModeFoldOut("_DissolveUVModeFoldOut",Float) = 0 + _DissolveLineFoldOut("_DissolveLineFoldOut",Float) = 0 + _DissolveRampFoldOut("_DissolveRampFoldOut",Float) = 0 + _DissolveRampUVModeFoldOut("_DissolveRampUVModeFoldOut",Float) = 0 + _DissolveMaskFoldOut("_DissolveMaskFoldOut",Float) = 0 + _DissolveMaskUVModeFoldOut("_DissolveMaskUVModeFoldOut",Float) = 0 + _ProgramNoiseBlockFoldOut("_ProgramNoiseBlockFoldOut",Float) = 0 + _ProgramNoiseUVModeFoldOut("_ProgramNoiseUVModeFoldOut",Float) = 0 + _ProgramNoiseSimpleFoldOut("_ProgramNoiseSimpleFoldOut",Float) = 0 + _ProgramNoiseVoronoiFoldOut("_ProgramNoiseVoronoiFoldOut",Float) = 0 + _SharedUVBlockFoldOut("_SharedUVBlockFoldOut",Float) = 0 + _SharedUVModeFoldOut("_SharedUVModeFoldOut",Float) = 0 + _FresnelBlockFoldOut("_FresnelBlockFoldOut",Float) = 0 + _VertexOffsetBlockFoldOut("_VertexOffsetBlockFoldOut",Float) = 0 + _VertexOffsetUVModeFoldOut("_VertexOffsetUVModeFoldOut",Float) = 0 + _VertexOffsetMaskBlockFoldOut("_VertexOffsetMaskBlockFoldOut",Float) = 0 + _VertexOffsetMaskUVModeFoldOut("_VertexOffsetMaskUVModeFoldOut",Float) = 0 + _DepthOutlineBlockFoldOut("_DepthOutlineBlockFoldOut",Float) = 0 + _ParallaxBlockFoldOut("_ParallaxBlockFoldOut",Float) = 0 + _ParallaxUVModeFoldOut("_ParallaxUVModeFoldOut",Float) = 0 + _PortalBlockFoldOut("_PortalBlockFoldOut",Float) = 0 + _VATBlockFoldOut("_VATBlockFoldOut",Float) = 0 + _ZOffsetBlockFoldOut("_ZOffsetBlockFoldOut",Float) = 0 + _OverrideZBlockFoldOut("_OverrideZBlockFoldOut",Float) = 0 + _CustomStencilTestFoldOut("_CustomStencilTestFoldOut",Float) = 0 + _ShaderKeywordFoldOut("_ShaderKeywordFoldOut",Float) = 0 + _MeshSourceMode("Mesh来源模式",Float) = 0 + _UIEffect_Toggle("UI模式_Toggle",Float) = 0 + _DistortionBothDirection_Toggle("__DistortionBothDirection_Toggle",Float) = 0 + _DistanceFade_Toggle("_DistanceFade_Toggle",Float) = 0 + _ChangeSaturability_Toggle("__ChangeSaturability_Toggle",Float) = 0 + _Mask_Toggle("__Mask_Toggle",Float) = 0 + _Mask_RotationToggle("__Mask_RotationToggle",Float) = 0 + _Mask2_Toggle("__Mask2_Toggle",Float) = 0 + _Mask3_Toggle("__Mask3_Toggle",Float) = 0 + _BaseBackColor_Toggle("__BaseBackColor_Toggle",Float) = 0 + _UseUV1_Toggle("__UseUV1_Toggle",Float) = 0 + _TransparentMode("_TransparentMode",Float) = 1 + _ForceZWriteToggle("_ForceZWriteToggle",Float) = 0 + _VAT_Toggle("VAT顶点动画图",Float) = 0 + _VATMode("VAT模式",Float) = 0 + [NoScaleOffset]_VATTex("VAT texture", 2D) = "black" {} + _ImportScale("ImportScale", Float) = 0.01 + [HideInInspector] _TyFlowVATSubMode("TyFlow VAT Sub Mode", Float) = 0 + _DeformingSkin("Deforming skin", Float) = 0 + _SkinBoneCount("Skin bone count", Float) = 2 + _RGBAEncoded("RGBA encoded", Float) = 1 + _RGBAHalf("RGBA half", Float) = 1 + _LinearToGamma("Gamma correction", Float) = 1 + _VATIncludesNormals("VAT includes normals", Float) = 0 + [HideInInspector] _HoudiniVATSubMode("Houdini VAT Sub Mode", Float) = 0 + [HideInInspector] _B_autoPlayback("Auto Playback", Float) = 1 + [HideInInspector] _gameTimeAtFirstFrame("Game Time at First Frame", Float) = 0 + [HideInInspector] _playbackSpeed("Playback Speed", Float) = 1 + [HideInInspector] _houdiniFPS("Houdini FPS", Float) = 24 + [HideInInspector] _displayFrame("Display Frame", Float) = 0 + [HideInInspector] _B_interpolate("Interframe Interpolation", Float) = 1 + [HideInInspector] _animateFirstFrame("Animate First Frame", Float) = 0 + [HideInInspector] _frameCount("Frame Count", Float) = 1 + [HideInInspector] _boundMinX("Bound Min X", Float) = -1 + [HideInInspector] _boundMinY("Bound Min Y", Float) = -1 + [HideInInspector] _boundMinZ("Bound Min Z", Float) = -1 + [HideInInspector] _boundMaxX("Bound Max X", Float) = 1 + [HideInInspector] _boundMaxY("Bound Max Y", Float) = 1 + [HideInInspector] _boundMaxZ("Bound Max Z", Float) = 1 + [HideInInspector] _globalPscaleMul("Global Piece Scale Multiplier", Float) = 1 + [HideInInspector] _B_pscaleAreInPosA("Piece Scales in Position Alpha", Float) = 1 + [HideInInspector] _widthBaseScale("Width Base Scale", Float) = 0.2 + [HideInInspector] _heightBaseScale("Height Base Scale", Float) = 0.2 + [HideInInspector] _B_hideOverlappingOrigin("Hide Overlapping Origin", Float) = 1 + [HideInInspector] _originRadius("Origin Effective Radius", Float) = 0.02 + [HideInInspector] _B_CAN_SPIN("Particles Can Spin", Float) = 0 + [HideInInspector] _B_spinFromHeading("Compute Spin from Heading", Float) = 0 + [HideInInspector] _spinPhase("Particle Spin Phase", Float) = 0 + [HideInInspector] _scaleByVelAmount("Scale by Velocity Amount", Float) = 1 + [HideInInspector] _particleTexUScale("Particle Texture U Scale", Float) = 1 + [HideInInspector] _particleTexVScale("Particle Texture V Scale", Float) = 1 + [HideInInspector] _B_LOAD_POS_TWO_TEX("Positions Require Two Textures", Float) = 0 + [HideInInspector] _B_UNLOAD_ROT_TEX("Use Compressed Normals", Float) = 0 + [HideInInspector] _B_LOAD_COL_TEX("Load Color Texture", Float) = 0 + [HideInInspector] _B_LOAD_LOOKUP_TABLE("Load Lookup Table", Float) = 0 + [HideInInspector][NoScaleOffset] _posTexture("Houdini Position Texture", 2D) = "black" {} + [HideInInspector][NoScaleOffset] _posTexture2("Houdini Position Texture 2", 2D) = "black" {} + [HideInInspector][NoScaleOffset] _rotTexture("Houdini Rotation Texture", 2D) = "black" {} + [HideInInspector][NoScaleOffset] _colTexture("Houdini Color Texture", 2D) = "white" {} + [HideInInspector][NoScaleOffset] _lookupTable("Houdini Lookup Table", 2D) = "white" {} + _AffectsShadows("Affects shadows", Float) = 0 + _TransparentShadowDitherToggle("半透明Dither阴影", Float) = 0 + _Frame("Frame", Float) = 0 + _Frames("Frames", Float) = 10 + _FrameInterpolation("Frame interpolation", Float) = 1 + _Loop("Loop", Float) = 1 + _InterpolateLoop("Interpolate loop", Float) = 1 + _Autoplay("Autoplay", Float) = 0 + _AutoplaySpeed("AutoplaySpeed", Float) = 1 + + _Dissolve_Toggle("__Dissolve_Toggle",Float) = 0 + _DissolveMask_Toggle("__DissolveMask_Toggle",Float) = 0 + _Dissolve_useRampMap_Toggle("__Dissolve_useRampMap_Toggle",Float) = 0 + _ProgramNoise_Toggle("_ProgramNoise_Toggle",Float) = 0 + _ProgramNoise_Simple_Toggle("_ProgramNoise_Simple_Toggle",Float) = 0 + _ProgramNoise_Rotate("_ProgramNoise_Rotate",Float) = 0 + _ProgramNoise_Voronoi_Toggle("_ProgramNoise_Voronoi_Toggle",Float) = 0 + _ProgramNoiseBaseBlendOpacity("两种程序噪波混合强度",Float) = 0 + + + _FresnelMode("__FresnelMode",Float) = 0 + _InvertFresnel_Toggle("__InvertFresnel_Toggle",Float) = 0 + _HueShift_Toggle("__HueShift_Toggle",Float) = 0 + _ColorAdjustmentOnlyAffectMainTex("颜色调整仅影响主贴图开关",Float) = 0 + _ColorMultiAlpha("颜色乘以透明度",Float) = 0 + _BackFaceColor_Toggle("_BackFaceColor_Toggle",Float) = 0 + _BackFirstPassToggle("_BackFirstPassToggle",Float) = 0 + + _PolarCordinateOnlySpecialFunciton_Toggle("极坐标仅对特殊功能生效_Toggle",Float) = 0 + + _CustomData1X_MainTexOffsetX_Toggle("_CustomData1X_MainTexOffsetX_Toggle",Float) = 0 + _CustomData1Y_MainTexOffsetY_Toggle("_CustomData1Y_MainTexOffsetY_Toggle",Float) = 0 + _CustomData1Z_Dissolve_Toggle("_CustomData1Z_Dissolve_Toggle",Float) = 0 + _CustomData1W_HueShift_Toggle("_CustomData1W_HueShift_Toggle",Float) = 0 + _CustomData2X_MaskMapOffsetX_Toggle("_CustomData2X_MaskMapOffsetX_Toggle",Float) = 0 + _CustomData2Y_MaskMapOffsetY_Toggle("_CustomData2Y_MaskMapOffsetY_Toggle",Float) = 0 + _CustomData2Z_FresnelOffset_Toggle("_CustomData2Z_FresnelOffset_Toggle",Float) = 0 + _CustomData2W_Toggle("_CustomData2W_Toggle",Float) = 0 + +// [PerRendererData] [MainTexture] _MainTex("Sprite Texture-ignore", 2D) = "white" {} + [PerRendererData] _MainTex ("Sprite Texture-ignore", 2D) = "white" {} + _Color("颜色贴图叠加", Color) = (1,1,1,1) + _UI_MainTex_ST("UI模式主贴图 xy:UV缩放 zw:UV偏移",vector) = (1,1,0,0) + _MainTex_Reverse_ST("MainTex_Reverse_ST-ignore",Vector) = (1,1,0,0) + + _BaseMap ("主贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _BaseMapMaskMapOffset ("xy主贴图偏移速度", vector) = (0, 0, 0, 0) + + _BaseMapUVRotation ("主贴图旋转", Range(0, 360)) = 0 + _BaseMapUVRotationSpeed ("主贴图旋转速度",Float) = 0 + [HDR]_BaseColor ("主贴图颜色_hdr", Color) = (1, 1, 1, 1)//HDR颜色不需要做Gamma Linear转换,Unity默认用Linear颜色 +// _BaseColor ("Base Color", Color) = (1, 1, 1, 1)//HDR颜色不需要做Gamma Linear转换,Unity默认用Linear颜色 + [HDR]_BaseBackColor ("背面颜色_hdr", Color) = (1, 1, 1, 1)//HDR颜色不需要做Gamma Linear转换,Unity默认用Linear颜色 + _BaseColorIntensityForTimeline("整体颜色强度", Range(0,10)) = 1 //独立出来是以为Timeline K颜色的时候会很奇怪的影响色相 + _Saturability("饱和度", range(0,1)) = 0 + _Contrast_Toggle("__Contrast_Toggle",Float) = 0 + _Contrast("对比度", Float) = 1 + _ContrastMidColor ("对比度中值颜色", Color) = (0.5, 0.5, 0.5, 1)//HDR颜色不需要做Gamma Linear转换,Unity默认用Linear颜色 + _HueShift("色相",Range(0,1)) = 0 + _BaseMapColorRefine_Toggle ("__BaseMapColorRefine_Toggle",Float) = 0 + _BaseMapColorRefine("主贴图颜色Refine",Vector) = (1,1,2,0.5) + _AlphaAll("整体透明度",Range(0,1)) = 1 + _IgnoreVetexColor_Toggle("_IgnoreVetexColor_Toggle",Float) = 0 + _MainTexPNoiseBlendOpacity("主贴图噪波图混合强度",Float) = 1 + + _SpecialUVChannelMode("特殊UV通道选择",Float) = 0 + + _CylinderUVRotate("圆柱UV旋转",Vector) = (0,0,90,0) + _CylinderUVPosOffset("圆柱UV位置偏移",Vector) = (0,0,0,0) + _CylinderMatrix0("圆柱偏移矩阵0",Vector) = (0,0,0,0) + _CylinderMatrix1("圆柱偏移矩阵1",Vector) = (0,0,0,0) + _CylinderMatrix2("圆柱偏移矩阵2",Vector) = (0,0,0,0) + _CylinderMatrix3("圆柱偏移矩阵3",Vector) = (0,0,0,0) + + _Cutoff ("裁剪位置", float) = 0.5 + + //--------------光照部分------------- + _FxLightMode("灯光模式",Float) = 0 + _BumpMapToggle("法线贴图开关",Float) = 0 + _BumpMapMaskMode("法线贴图多通道模式",Float) = 0 + _BumpScale("Scale", Float) = 1.0 + _BumpTex("Normal Map", 2D) = "bump" {} + _MaterialInfo("x:金属度,y:光滑度",Vector) = (1,1,0,0) + _BlinnPhongSpecularToggle("BlinnPhong高光开关",Float) = 0 + [HDR]_SpecularColor("BlinnPhong高光颜色",Color) = (1,1,1,1) + //-----------SixWayLight---------- + _RigRTBk("六路正方向图(P)",2D) = "white"{} + _RigLBtF("六路反方向图(N)",2D) = "white"{} + _SixWayColorAbsorptionToggle("六路光颜色吸收开关",Float) = 0 + _SixWayInfo("x:六路吸收强度",Vector) = (0.5,0,0,0) + _SixWayEmissionRamp("六路自发光Ramp",2D) = "white"{} + [HDR]_SixWayEmissionColor("六路自发光颜色",Color) = (1,0.5,0,1) + + //-----MatCap------ + _MatCapToggle("MatCap开关",Float) = 0 + _MatCapTex("MatCap图",2D) = "white"{} + [HDR]_MatCapColor("MatCap颜色",Color) = (1,1,1,1) + _MatCapInfo("x:MatCap叠加和相乘过渡",Vector) = (1,0,0,0) +// _MatCapBlendMode("MatCap叠加模式",Float) = 0 + + //时间缩放影响开关---------- + [HideInInspector] _TimeMode("__TimeMode",float) = 0.0 + + _StencilWithoutPlayerToggle("剔除主角色开关",Float) = 0.0 + + // MaskMap----------- + _MaskRefineToggle("遮罩整体调整开关",Float) = 0 + _MaskRefineVec("遮罩整体调整:x:Pow,y:相乘,z:相加",Vector) = (1,1,0,0) + _MaskMap ("遮罩贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _MaskMap2 ("遮罩2贴图 xy:UV缩放 zw:UV偏移", 2D) = "white"{} + _MaskMap3 ("遮罩3贴图 xy:UV缩放 zw:UV偏移", 2D) = "white"{} + _MaskMapOffsetAnition("xy:遮罩偏移速度,zw:遮罩2偏移速度", vector) = (0,0,0,0) + _MaskMap3OffsetAnition("xy:遮罩3偏移速度", vector) = (0,0,0,0) + _MaskMapUVRotation ("遮罩旋转", Range(0, 360)) = 0.0 + _MaskDistortion_intensity ("遮罩扭曲强度", float) = 0.0 + _MaskMapRotationSpeed("遮罩旋转速度", float) = 0.0 + _MaskMapVec("x整体遮罩强度,y遮罩2旋转,z遮罩3旋转",Vector) = (1,0,0,0) + + _MaskMapGradientToggle("遮罩渐变模式",Float) = 0 + _MaskMapGradientCount("颜色映射数量",Integer) = 2 + _MaskMapGradientFloat0("x:MaskAlpha0,y:Pos0,z:MaskAlpha1,w:Pos1",Vector) = (0,0,1,1) + _MaskMapGradientFloat1("x:MaskAlpha2,y:Pos2,z:MaskAlpha3,w:Pos3",Vector) = (1,0,1,1) + _MaskMapGradientFloat2("x:MaskAlpha4,y:Pos4,z:MaskAlpha5,w:Pos5",Vector) = (1,0,1,1) + _MaskMap2GradientToggle("遮罩2渐变模式",Float) = 0 + _MaskMap2GradientCount("颜色映射数量",Integer) = 2 + _MaskMap2GradientFloat0("x:Mask2Alpha0,y:Pos0,z:Mask2Alpha1,w:Pos1",Vector) = (0,0,1,1) + _MaskMap2GradientFloat1("x:Mask2Alpha2,y:Pos2,z:Mask2Alpha3,w:Pos3",Vector) = (1,0,1,1) + _MaskMap2GradientFloat2("x:Mask2Alpha4,y:Pos4,z:Mask2Alpha5,w:Pos5",Vector) = (1,0,1,1) + _MaskMap3GradientToggle("遮罩3渐变模式",Float) = 0 + _MaskMap3GradientCount("颜色映射数量",Integer) = 2 + _MaskMap3GradientFloat0("x:Mask3Alpha0,y:Pos0,z:Mask3Alpha1,w:Pos1",Vector) = (0,0,1,1) + _MaskMap3GradientFloat1("x:Mask3Alpha2,y:Pos2,z:Mask3Alpha3,w:Pos3",Vector) = (1,0,1,1) + _MaskMap3GradientFloat2("x:Mask3Alpha4,y:Pos4,z:Mask3Alpha5,w:Pos5",Vector) = (1,0,1,1) + _MaskPNoiseBlendOpacity("遮罩噪波图混合强度",Float) = 1 + + // 擦除---------------- + //[Header(ChaChu(Anima For CustomData.z).......)] + //[KeywordEnum(NoChange,XianXing, JingXiang, Self)] _ch ("ChaChu mode", Float) = 0 + [HideInInspector] _Chachu ("__Chachu_ignore", Float) = 0.0 + _EdgeFade ("EdgeFade_ignore", Range(0, 1)) = 0.05 + _XianXingCH_UVRota ("XianXingCH_UVRota_ignore", float) = 0 + _jingxiangCH_dire ("Direction_ignore", Range(0, 1)) = 0 + + // 漩涡 ------------------- + //[Toggle(_JIZUOBIAO)] _N121 ("JIZUOBIAO?", float) = 0 + [HideInInspector] _UTwirlEnabled ("__UTwirlEnabled", Float) = 0.0 + _TWParameter ("xy:旋转扭曲中心", vector) = (0.5, 0.5, 0, 0) + _TWStrength ("旋转扭曲强度", float) = 1 + + + // 极坐标 ------------------- + //[Toggle(_JIZUOBIAO)] _N121 ("JIZUOBIAO?", float) = 0 + [HideInInspector]_PolarCoordinatesEnabled ("__PolarCoordinatesEnabled", Float) = 0.0 + _PCCenter ("xy:极坐标中心 z:极坐标强度", vector) = (0.5, 0.5, 1, 0)//位置坐标用的前两个分量,z分量给强度。 + + // 噪波 -------------- + //[Toggle(_NOISEMAP)]_N ("NOISEMAP?", float) =0 + [HideInInspector] _ScreenDistortModeToggle("_ScreenDistortModeToggle",Float) = 0 + [HideInInspector] _DisableMainPassToggle("_ScreenDistortModeToggle",Float) = 0 + [HideInInspector] _DistortMode("_DistortMode",Float) = 0 + [HideInInspector] _noisemapEnabled ("__noisemapEnabled", Float) = 0.0 + [HideInInspector] _noiseMaskMap_Toggle ("__noiseMaskMap_Toggle", Float) = 0.0 + _RefractionIOR("折射率",Float) = 1.5 + _NoiseMap ("扭曲贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _NoiseMaskMap ("扭曲遮罩贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _NoiseMapUVRotation("扭曲旋转",Range(0,360)) = 0 + _NoiseOffset ("xy:扭曲偏移速度 ", vector) = (0, 0, 0, 0)//w分量为本地uv坐标到世界坐标的变化 + _TexDistortion_intensity ("主贴图扭曲强度", float) = 0.5 + _NoiseIntensity("整体扭曲强度",Float) = 1 + _ScreenDistortIntensity("屏幕扭曲强度",Float) = 1 + _DistortPNoiseBlendOpacity("扭曲噪波图混合强度",Float) = 1 + + _ScreenDistortAlphaRefineToggle("屏幕扭曲Alpha调整开关",Float) = 0 + _ScreenDistortAlphaPow("屏幕扭曲AlphaPow",Float) = 1 + _ScreenDistortAlphaMulti("屏幕扭曲Alpha相乘",Float) = 1 + _ScreenDistortAlphaAdd("屏幕扭曲Alpha相加",Float) = 0 + _DistortionDirection ("扭曲方向xy, 色散强度z", vector) = (1,1,0,0) + _Distortion_Choraticaberrat_Toggle("扭曲色散开关_Toggle",Float) = 0 + _Distortion_Choraticaberrat_WithNoise_Toggle("色散受扭曲影响_Toggle",Float) = 1 + + // 流光 ---------- + //[Header(LiuGuang(Anima For CustomData.w).......)] + //[Toggle(_EMISSION)]_N1 ("EMISSION?", float) = 0 + [HideInInspector] _EmissionEnabled ("__EmissionEnabled", Float) = 0.0 + _EmissionMap ("流光贴图 xy:UV缩放 zw:UV偏移", 2D) = "white" { } + _EmissionMapUVRotation ("流光贴图旋转", Range(0, 360)) = 0 + _Emi_Distortion_intensity ("流光贴图扭转强度", float) = 0 + _EmissionMapUVOffset ("xy:流光贴图偏移速度", vector) = (0, 0, 0, 0) + _EmissionSelfAlphaWeight ("__EmissionSelfAlphaWeight_ignore", float) = 0 + _uvRapSoft ("LiuuvRapSoft-ignore", Range(0, 1)) = 0 + [HDR]_EmissionMapColor ("流光贴图颜色_hdr", Color) = (1, 1, 1, 1) + _EmissionMapColorIntensity("流光颜色强度", float) = 1 + + //颜色渐变贴图-------- + _ColorBlendMap_Toggle("__ColorBlendMap_Toggle",Float) = 0 + _ColorBlendMap("颜色渐变贴图 xy:UV缩放 zw:UV偏移",2D) = "white"{} + [HDR]_ColorBlendColor("颜色渐变叠加_hdr",Color) = (1,1,1,1) + _ColorBlendMapOffset("xy:颜色渐变贴图偏移动画",Vector) = (0,0,0,0) + _ColorBlendAlphaMultiplyMode("颜色渐变Alpha相乘开关",Float) = 0 + _ColorBlendVec("x:颜色渐变扰动强度z:Alpha强度w:旋转",Vector) = (0,0,1,0) + + //颜色映射Ramp + _RampColorToggle("颜色映射开关",Float) = 0 + _RampColorSourceMode("Ramp来源模式",Float) = 0 + _RampColorBlendMode("Ramp颜色混合模式",Float) = 0 + _RampColorMap("颜色映射黑白图",2D) = "white"{} + _RampColor0("rgb:RampColor0,a:pos",Color) = (0,0,0,0) + _RampColor1("rgb:RampColor1,a:pos",Color) = (1,0,0,1) + _RampColor2("rgb:RampColor2,a:pos",Color) = (1,1,1,1) + _RampColor3("rgb:RampColor3,a:pos",Color) = (1,1,1,1) + _RampColor4("rgb:RampColor4,a:pos",Color) = (1,1,1,1) + _RampColor5("rgb:RampColor5,a:pos",Color) = (1,1,1,1) + _RampColorAlpha0("x:RampColorAlpha0,y:Pos0,z:RampColorAlpha1,w:Pos1",Vector) = (1,0,1,1) + _RampColorAlpha1("x:RampColorAlpha2,y:Pos2,z:RampColorAlpha3,w:Pos3",Vector) = (1,0,1,1) + _RampColorAlpha2("x:RampColorAlpha4,y:Pos4,z:RampColorAlpha5,w:Pos5",Vector) = (1,0,1,1) + _RampColorCount("颜色映射数量",Integer) = 131074 + [HDR]_RampColorBlendColor("颜色映射叠加颜色_hdr",Color) = (1,1,1,1) + _RampColorMapOffset("xy:颜色映射贴图偏移动画,w:旋转",Vector) = (0,0,0,0) + + + // Rongjie ------------------ + // [Header(RongJie(Anima For CustomData.y).......)] + // [Toggle(_DISSOLVE)]_RJ ("RONGJIE?", float) = 0 + _Dissolve ("x:溶解强度 y:溶解值Pow z:过程溶解强度 w:溶解硬软度", vector) = (0.5, 1, 1, 0.1) + _DissolveMap("溶解贴图 xy:UV缩放 zw:UV偏移",2D) = "grey"{} + _DissolveMaskMap("局部溶解蒙版 xy:UV缩放 zw:UV偏移",2D) = "white"{} + _DissolveMaskMode("溶解遮罩模式", Float) = 0 + _DissolveOffsetRotateDistort("xy:溶解贴图偏移速度 z:溶解贴图旋转",Vector) = (0,0,0,0) + [HDR]_DissolveLineColor("溶解描边颜色_hdr",Color) = (1,0,0,1) + _DissolveVoronoi_Vec("xy:噪波1缩放,zw:噪波2缩放",Vector) = (1,1,2,2) + _DissolveVoronoi_Vec2("x:噪波1和噪波2混合系数(圆尖),y:噪波整体和溶解贴图混合系数,z:噪波1速度,w:噪波2速度",Vector) = (1,1,2,2) + _DissolveVoronoi_Vec3("xy:噪波1偏移速度,zw:噪波2偏移速度",Vector) = (0,0,0,0) + _DissolveVoronoi_Vec4("xy:噪波1偏移,zw:噪波2偏移",Vector) = (0,0,0,0) + _Dissolve_Vec2("x:Ramp位置偏移,y:Ramp范围",Vector) = (0.2,0.1,0,0) + _DissolveRampMap("溶解Ramp图",2D) = "white"{} + _DissolveRampColorBlendMode("溶解Ramp图混合模式",Float) = 0 + [HDR]_DissolveRampColor("溶解Ramp颜色_hdr",Color) = (1,1,1,1) + _DissolveLineMaskToggle("溶解描边开关",Float) = 0 + + _DissolveRampSourceMode("溶解Ramp来源模式",Float) = 0 + _DissolveRampColor0("rgb:DissolveRampColor0,a:pos",Color) = (1,0,0,0) + _DissolveRampColor1("rgb:DissolveRampColor1,a:pos",Color) = (0,0,0,1) + _DissolveRampColor2("rgb:DissolveRampColor2,a:pos",Color) = (1,1,1,1) + _DissolveRampColor3("rgb:DissolveRampColor3,a:pos",Color) = (1,1,1,1) + _DissolveRampColor4("rgb:DissolveRampColor4,a:pos",Color) = (1,1,1,1) + _DissolveRampColor5("rgb:DissolveRampColor5,a:pos",Color) = (1,1,1,1) + _DissolveRampAlpha0("x:DissolveRampAlpha0,y:Pos0,z:DissolveRampAlpha1,w:Pos1",Vector) = (1,0,1,1) + _DissolveRampAlpha1("x:DissolveRampAlpha2,y:Pos2,z:DissolveRampAlpha3,w:Pos3",Vector) = (1,0,1,1) + _DissolveRampAlpha2("x:DissolveRampAlpha4,y:Pos4,z:DissolveRampAlpha5,w:Pos5",Vector) = (1,0,1,1) + _DissolveRampCount("溶解Ramp映射数量",Integer) = 131074 + _DissolvePNoiseBlendOpacity("溶解噪波图混合强度",Float) = 1 + + _SharedUVToggle("公共UV开关",Float) = 0 + _SharedUV_ST("公共UVTillingOffset",Vector) = (1,1,0,0) + _SharedUV_Vec("xy:公共UV偏移速度,z:旋转,w:旋转速度",Vector) = (0,0,0,0) + + + _CustomData1X ("ignore", float) = 0 + _CustomData1Y ("ignore", float) = 0 + //因为希望本Shader兼容CanvasRender,由于Canvas渲染只会传递TEXCOORD通道的xy分量(zw分量忽略)的特性,所以强制让CustomedData只传递xy分量。 + _CustomData2X ("ignore", float) = 0 + + // ------------------------------------- + // Particle specific 属于粒子特殊的属性 + [ToggleOff] _CustomData ("__CustomData_Toggle", Float) = 0.0 //Toggleoff 和 Toggle 的区别 + [ToggleOff] _FlipbookBlending ("__flipbookblending_Toggle", Float) = 0.0 //Toggleoff 和 Toggle 的区别 +// _SoftParticlesNearFadeDistance ("Soft Particles Near Fade", Float) = 0.0 +// _SoftParticlesFarFadeDistance ("Soft Particles Far Fade", Float) = 1.0 + //[Toggle] _Fading ("Fading? =Default(1,2,0,0)", Float) = 0.0 + _CameraNearFadeDistance ("Camera Near Fade-ignore", Float) = 1.0 + _CameraFarFadeDistance ("Camera Far Fade-ignore", Float) = 2.0 + //临时 + _fogintensity ("雾影响强度", Range(0, 1)) = 1 + // ------------------------------------- + // Hidden properties - Generic 通用的隐藏属性 + _AdditiveToPreMultiplyAlphaLerp("相加到预乘混合",Float) = 0.0 + [HideInInspector] _Blend ("__mode-ignore", Float) = 0.0 + [HideInInspector] _AlphaClip ("__clip-ignore", Float) = 0.0 + [HideInInspector] _SrcBlend ("__src-ignore", Float) = 1.0 + [HideInInspector] _DstBlend ("__dst-ignore", Float) = 0.0 + [HideInInspector] _Cull ("__cull-ignore", Float) = 2.0 + [HideInInspector] _ZTest ("__ztest-ignore", Float) = 4.0 //默认值LEqual + [HideInInspector] _ZWrite("__ZWrite-ignore", Float) = 0 //默认值LEqual + // [HideInInspector] _ZTestt ("__ztestt", Float) = 4.0//雨轩:注释掉了。。。这是个什么鬼。。。 + + _CustomStencilTest ("__CustomStencilTest-ignore", Float) = 0 + _StencilKeyIndex("__StencilKeyIndex-ignore",Float) = 0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp ("__StencilComp-ignore", Float) = 8 + _Stencil("Stencil ID-ignore", Float) = 0 + [Enum(UnityEngine.Rendering.StencilOp)]_StencilOp("Stencil Operation-ignore", Float) = 0 + [Enum(UnityEngine.Rendering.StencilOp)]_StencilFail("Stencil Fail-ignore", Float) = 0 + [Enum(UnityEngine.Rendering.StencilOp)]_StencilZFail("Stencil ZFail-ignore", Float) = 0 + _StencilWriteMask ("Stencil Write Mask-ignore", Float) = 255 + _StencilReadMask ("Stencil Read Mask-ignore", Float) = 255 + _ColorMask("Color Mask-ignore", Float) = 15 + + //[HideInInspector] _ZTestO ("__ztest0", Float) = 1.0 + _FresnelFadeDistance ("菲涅尔透明乘数", float) = 1 + _FresnelUnit("菲涅尔通用", Vector) = (0,0.5,1,0.5) + + _DepthOutline_Toggle("深度描边",Float) = 0 + [HDR]_DepthOutline_Color("深度描边颜色_hdr",Color) = (1,1,1,1) + _DepthOutline_Vec("菲涅尔深度描边参数",Vector) = (0,0.5,0,0) + _FresnelColorAffectByAlpha("菲涅尔颜色受Alpha影响",Float) = 1 +// _DepthOutline_withoutFresnel_Toggle("深度描边关闭菲涅尔",Float) = 0 +// _FresnelUnit2("菲涅尔通用2", Vector) = (1,1,0,0) + + _DepthDecal_Toggle("深度贴花",Float) = 0 + + _VertexOffset_Toggle("顶点偏移",Float) = 0 + _VertexOffset_Map("顶点偏移贴图",2D) = "white"{} + _VertexOffset_Vec("xy:顶点偏移动画z:顶点偏移强度",Vector) = (0,0,1,0) + _VertexOffset_NormalDir_Toggle("顶点偏移自定义方向开关",Float) = 0 + _VertexOffset_StartFromZero("顶点偏移从零开始开关",Float) = 0 + _VertexOffset_CustomDir("顶点偏移自定义方向",Vector) = (1,1,1,0) + + _VertexOffset_Mask_Toggle("顶点偏移遮罩开关",Float) = 0 + _VertexOffset_MaskMap("顶点偏移遮罩贴图",2D) = "white"{} + _VertexOffset_MaskMap_Vec("xy:顶点偏移遮罩动画z:顶点偏移遮罩强度",Vector) = (0,0,1,0) + + + _ParallaxMapping_Toggle("视差",Float) = 0 + _ParallaxMapping_Map("视差贴图",2D) = "white"{} + _ParallaxMapping_Intensity("视差强度",Float) = 0.05 + _ParallaxMapping_Vec("遮蔽视差层数 x:最小值,y:最大值",Vector) = (5,30,0,0) + + + // Particle specific 粒子特殊的隐藏属性 + [HideInInspector] _ColorMode ("_ColorMode", Float) = 0.0 + [HideInInspector] _BaseColorAddSubDiff ("_ColorMode", Vector) = (0, 0, 0, 0) + [HideInInspector] _SoftParticlesEnabled ("__softparticlesenabled", Float) = 0.0 + [HideInInspector] _CameraFadingEnabled ("__camerafadingenabled", Float) = 0.0 + [HideInInspector] _SoftParticleFadeParams ("xy:软粒子远近裁剪面", Vector) = (0, 0.5, 0, 0) + [HideInInspector] _CameraFadeParams ("__camerafadeparams_ignore", Vector) = (0, 0, 0, 0) + [HideInInspector] _IntersectEnabled("__IntersectEnabled_ignore",Float) = 0.0 + [HideInInspector] _IntersectRadius("__IntersectRadius_ignore",Float) = 0.3 + [HideInInspector] _IntersectColor("__IntersectColor_ignore",Color) = (1,1,1,1) + + + // Editmode props 编辑模式下的PropFlags? + [HideInInspector] _QueueBias ("Queue偏移_QueueBias", Float) =0 + + // ObsoleteProperties 弃用的属性???? + [HideInInspector] _FlipbookMode ("flipbook mode", Float) = 0 + [HideInInspector] _Mode ("mode", Float) = 0 + // [HideInInspector] _Color ("color", Color) = (1, 1, 1, 1) + + [HideInInspector]_fresnelEnabled ("__fresnelEnabled", Float) = 0.0 + [NoScaleOffset]_FresnelHDRITex("__FresnelHDRITex_ignore",Cube) = "white"{} + [HDR]_FresnelColor ("菲涅尔颜色_hdr", COLOR) = (1, 1, 1, 1) + _FresnelRotation("菲涅尔方向偏移",vector) = (0,0,0,0.5) + _FresnelInOutSlider ("direction-ignore", Range(0, 1)) = 1 + _FrePower ("FrePower-ignore", Range(0,1)) = 0.5 + _FresnelSelfAlphaWeight("__FresnelSelfAlphaWeight-ignore",float) = 0 + //用于程序控制透明属性 + [HideInInspector] _ColorA ("ColorA-ignore", Color) = (1,1,1,1) + + _Portal_Toggle("模板视差开关",Float) = 0 + _Portal_MaskToggle("模板视差蒙版开关",Float) = 0 + + //基于深度的a通道控制 + [HideInInspector] _Fade("xy:近距离透明过度范围", Vector) = (2,4,0,0) + + [HideInInspector] _InspectorData("__InspectorData-ignore",vector) = (1,1,0,0) + + [Header(ZOffset)] + _ZOffset_Toggle("深度偏移_Toggle",Float) = 0 + _offsetFactor("深度偏移Sacle-ignore", range(-2000,2000)) = 0 + _offsetUnits("深度偏移单位距离-ignore", range(-2000,2000)) = 0 + _OverrideZ_Toggle("Override Z Toggle-ignore",Float) = 0 + _OverrideZValue("Override Z Value-ignore",Float) = 1000 + + _WorldSpaceUVModeSelector("_WordSpaceUVModeSelector",Float) = 1 + _ObjectSpaceUVModeSelector("_ObjectSpaceUVModeSelector",Float) = 1 + + [HideInInspector] _W9ParticleShaderFlags("_W9ParticleShaderFlags", Integer) = 0 + [HideInInspector] _W9ParticleShaderFlags1("_W9ParticleShaderFlags1", Integer) = 1 + [HideInInspector] _W9ParticleShaderWrapFlags("_W9ParticleShaderWrapFlags", Integer) = 0 + [HideInInspector] _W9ParticleShaderWrapFlags2("_W9ParticleShaderWrapFlags2", Integer) = 0 + [HideInInspector] _W9ParticleCustomDataFlag0("_W9ParticleCustomDataFlag0", Integer) = 0 + [HideInInspector] _W9ParticleCustomDataFlag1("_W9ParticleCustomDataFlag1", Integer) = 0 + [HideInInspector] _W9ParticleCustomDataFlag2("_W9ParticleCustomDataFlag2", Integer) = 0 + [HideInInspector] _W9ParticleCustomDataFlag3("_W9ParticleCustomDataFlag3", Integer) = 0 + [HideInInspector] _UVModeFlag0("_UVModeFlag0", Integer) = 0 + [HideInInspector] _UVModeFlagType0("_UVModeFlagType0", Integer) = 0 + [HideInInspector] _NBShaderGUIFoldToggle("_NBShaderGUIFoldToggle", Integer) = 3//前2个开关默认打开 + [HideInInspector] _NBShaderGUIFoldToggle1("_NBShaderGUIFoldToggle1", Integer) = 255//这边默认全开 + [HideInInspector] _NBShaderGUIFoldToggle2("_NBShaderGUIFoldToggle2", Integer) = 255//这边默认全开 + [HideInInspector] _W9ParticleShaderColorChannelFlag("_W9ParticleShaderColorChannelFlag", Integer) = 3//默认主贴图开A通道 + [HideInInspector] _W9ParticleShaderPNoiseBlendFlag("_W9ParticleShaderPNoiseBlendFlag", Integer) = 0 + + + SaturabilityRangeVec("_Saturability",Vector) = (0,1,0,0) + TexDistortionintensityRangeVec("_TexDistortion_intensity",Vector) = (-1,1,0,0) + MaskDistortionIntensityRangeVec("_MaskDistortion_intensity",Vector) = (-2,2,0,0) + EmiDistortionIntensityRangeVec("_TexDistortion_intensity",Vector) = (-1,1,0,0) + BumpScaleRangeVec("_BumpScale",Vector) = (-1,1,0,0) + DissolveXRangeVec("_Dissolve.x",Vector) = (-1,2,0,0) + Dissolve2XRangeVec("_Dissolve_Vec2.x",Vector) = (0,1,0,0) + Dissolve2YRangeVec("_Dissolve_Vec2.y",Vector) = (0,1,0,0) + AlphaAllRangeVec("_AlphaAll",Vector) = (0,1,0,0) + _NoiseIntensityRangeVec("_NoiseIntensity",Vector) = (0,1,0,0) + _ScreenDistortIntensityRangeVec("_ScreenDistortIntensity",Vector) = (0,1,0,0) + _ParallaxMapping_IntensityRangeVec("_ParallaxMappingRangeVec",Vector) = (0,0.1,0,0) +// _offsetUnits("深度偏移单位距离-ignore", range(-2000,2000)) = 0 + _NB_Debug_Mask("_NB_Debug_Mask",Float) = 0 + _NB_Debug_PNoise("_NB_Debug_PNoise",Float) = 0 + _NB_Debug_Dissolve("_NB_Debug_Dissolve",Float) = 0 + _NB_Debug_Distort("_NB_Debug_Dissolve",Float) = 0 + _NB_Debug_Fresnel("_NB_Debug_Fresnel",Float) = 0 + _NB_Debug_VertexOffset("_NB_Debug_VertexOffset",Float) = 0 + } + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Sphere" "CanUseSpriteAtlas"="True" } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + Fail [_StencilFail] + ZFail [_StencilZFail] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + //BlendOp[_BlendOp] //考虑注释~ + Blend[_SrcBlend][_DstBlend] + ZWrite [_ZWrite]//粒子不写入深度缓冲 + ZTest[_ZTest] + + ColorMask [_ColorMask] + + // ------------------------------------------------------------------ + // 预渲染反面Pass,基本理念。先剔除正面棉片,渲染反面面片(一般在后),然后常规Pass再渲染正面(一般在前) + // 这样可以应对大部分的特效半透明渲染的次序问题。 + // URP下的多Pass渲染,需要使用特定的LightModeTag: + // https://zhuanlan.zhihu.com/p/469589277#:~:text=%E6%B3%A8%E6%84%8F%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%85%89%E7%85%A7pass%E7%9A%84%E5%85%89%E7%85%A7tag%E4%B8%BA%20%22LightMode%22%20%3D%20%22SRPDefaultUnlit%22%EF%BC%8C%E8%BF%99%E6%98%AF%E5%9B%A0%E4%B8%BA%E5%BF%85%E9%A1%BB%E8%AE%BE%E7%BD%AE%E4%B8%BA%E7%89%B9%E5%AE%9A%E7%9A%84%E5%87%A0%E4%B8%AALightMode%20%E6%89%8D%E8%83%BD%E6%AD%A3%E7%A1%AE%E8%A2%AB%E6%B8%B2%E6%9F%93%E3%80%82%E5%85%B7%E4%BD%93%E5%93%AA%E5%87%A0%E4%B8%AA%20LightMode%20%E8%A7%81URP%E5%8C%85%E9%87%8C%E7%9A%84%20Runtime/Passes%20%E9%87%8C%E7%9A%84%20DrawObjectsPass.cs%E8%84%9A%E6%9C%AC%EF%BC%8C%E9%87%8C%E9%9D%A2%E6%9C%89%E5%A6%82%E4%B8%8B%E4%BB%A3%E7%A0%81%EF%BC%9A + // 开关Pass,同样也需要用到LightTag + // https://blog.csdn.net/shaoy1234567/article/details/106494878 + + Pass + { + Tags + { + "LightMode" = "SRPDefaultUnlit" "Queue"="Opaque" + } + offset [_offsetFactor], [_offsetUnits] + Name "SRPDefaultUnlit" + Cull Front + + HLSLPROGRAM + #define PARTICLE + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + + #pragma exclude_renderers d3d11_9x + #pragma exclude_renderers d3d9 + + #include_with_pragmas "Packages/com.xuanxuan.nb.fx/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl" + + // ------------------------------------- + // Material Keywords + // #pragma shader_feature_local _ _SCREEN_DISTORT_MODE + #pragma shader_feature_local _ _DISTORT_REFRACTION + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _MASKMAP2_ON + #pragma shader_feature_local _MASKMAP3_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISE_MASKMAP + #pragma shader_feature_local_fragment _CHROMATIC_ABERRATION + //#pragma shader_feature_local _EMISSION //流光 + #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _DISSOLVE_MASK + #pragma shader_feature_local_fragment _DISSOLVE_RAMP + #pragma shader_feature_local_fragment _DISSOLVE_RAMP_MAP + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _PROGRAM_NOISE_SIMPLE + #pragma shader_feature_local _PROGRAM_NOISE_VORONOI + #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local_fragment _COLOR_RAMP_MAP + #pragma shader_feature_local _SHARED_UV//公共UV + #pragma shader_feature_local _ _VAT _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _ _VAT_HOUDINI _VAT_TYFLOW + #pragma shader_feature_local_vertex _ _HOUDINI_VAT_SOFTBODY _HOUDINI_VAT_RIGIDBODY _HOUDINI_VAT_DYNAMIC_REMESH _HOUDINI_VAT_PARTICLE_SPRITE + #pragma shader_feature_local_vertex _ _TYFLOW_VAT_ABSOLUTE _TYFLOW_VAT_RELATIVE _TYFLOW_VAT_SKIN_R _TYFLOW_VAT_SKIN_PR _TYFLOW_VAT_SKIN_PRSAVE _TYFLOW_VAT_SKIN_PRSXYZ + + //将光照和UI混用,达到节省Keywords的目的。 + #pragma multi_compile _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS//UI 2D遮罩 + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + + // #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local_vertex _VERTEX_OFFSET + #pragma shader_feature_local_vertex _VERTEX_OFFSET_MASKMAP + + #pragma shader_feature_local_fragment _FRESNEL + + + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + + #pragma shader_feature_local _DEPTH_DECAL + #pragma shader_feature_local _DEPTH_OUTLINE + #pragma shader_feature_local _DISTANCE_FADE + #pragma shader_feature_local _PARALLAX_MAPPING + #pragma shader_feature_local_fragment _OVERRIDE_Z + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT _FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _ _NORMALMAP + #pragma shader_feature_local _ _MATCAP + #pragma shader_feature_local _ _SPECULAR_COLOR + #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + #pragma shader_feature_local _ NB_DEBUG_MASK NB_DEBUG_PNOISE NB_DEBUG_DISSOLVE NB_DEBUG_DISTORT NB_DEBUG_FRESNEL NB_DEBUG_VERTEX_OFFSET + + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + + // #if defined(_SOFTPARTICLES_ON) + // #define NEED_EYE_DEPTH + // #endif + + #define PARTICLE_BACKFACE_PASS + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + // #include "UnityCG.cginc" + // #include "AutoLight.cginc" + // #include "UnityUI.cginc" + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + + #include "HLSL/NBShaderForwardPass.hlsl" + + ENDHLSL + + } + + // ------------------------------------------------------------------ + // Forward pass. + Pass + { + Name "UniversalForward" + Tags + { + "LightMode" = "UniversalForward" + } //Queue设置是希望特效渲染在场景透明物体前面 + offset [_offsetFactor], [_offsetUnits] + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + //20240228 target3.0 顶点着色器限制16个输出。提高版本 + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + // ------------------------------------- + // Material Keywords + + #include_with_pragmas "Packages/com.xuanxuan.nb.fx/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl" + + // #pragma shader_feature_local _ _SCREEN_DISTORT_MODE + #pragma shader_feature_local _ _DISTORT_REFRACTION + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _MASKMAP2_ON + #pragma shader_feature_local _MASKMAP3_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISE_MASKMAP + #pragma shader_feature_local_fragment _CHROMATIC_ABERRATION + //#pragma shader_feature_local _EMISSION //流光 + #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _DISSOLVE_MASK + #pragma shader_feature_local_fragment _DISSOLVE_RAMP + #pragma shader_feature_local_fragment _DISSOLVE_RAMP_MAP + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _PROGRAM_NOISE_SIMPLE + #pragma shader_feature_local _PROGRAM_NOISE_VORONOI + #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local_fragment _COLOR_RAMP_MAP + #pragma shader_feature_local _SHARED_UV//公共UV + #pragma shader_feature_local _ _VAT _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _ _VAT_HOUDINI _VAT_TYFLOW + #pragma shader_feature_local_vertex _ _HOUDINI_VAT_SOFTBODY _HOUDINI_VAT_RIGIDBODY _HOUDINI_VAT_DYNAMIC_REMESH _HOUDINI_VAT_PARTICLE_SPRITE + #pragma shader_feature_local_vertex _ _TYFLOW_VAT_ABSOLUTE _TYFLOW_VAT_RELATIVE _TYFLOW_VAT_SKIN_R _TYFLOW_VAT_SKIN_PR _TYFLOW_VAT_SKIN_PRSAVE _TYFLOW_VAT_SKIN_PRSXYZ + + + + #pragma multi_compile_local _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //UI 2D遮罩 + // #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local_vertex _VERTEX_OFFSET + #pragma shader_feature_local_vertex _VERTEX_OFFSET_MASKMAP + + #pragma shader_feature_local_fragment _FRESNEL + + + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + + #pragma shader_feature_local _DEPTH_DECAL + #pragma shader_feature_local _DEPTH_OUTLINE + #pragma shader_feature_local _DISTANCE_FADE + #pragma shader_feature_local _PARALLAX_MAPPING + #pragma shader_feature_local_fragment _OVERRIDE_Z + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT _FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _ _NORMALMAP + #pragma shader_feature_local _ _MATCAP + #pragma shader_feature_local _ _SPECULAR_COLOR + #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + #pragma shader_feature_local _ NB_DEBUG_MASK NB_DEBUG_PNOISE NB_DEBUG_DISSOLVE NB_DEBUG_DISTORT NB_DEBUG_FRESNEL NB_DEBUG_VERTEX_OFFSET + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera + // depth texture. + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/NBShaderForwardPass.hlsl" + + + ENDHLSL + + } + + Pass + { + Name "DepthOnly" + Tags + { + "LightMode" = "DepthOnly" + } + + Blend One Zero + ZWrite On + ZTest LEqual + ColorMask R + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + #define _FX_LIGHT_MODE_UNLIT + #define NB_DEPTH_ONLY_PASS + + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _MASKMAP2_ON + #pragma shader_feature_local _MASKMAP3_ON + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISE_MASKMAP + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _DISSOLVE_MASK + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _PROGRAM_NOISE_SIMPLE + #pragma shader_feature_local _PROGRAM_NOISE_VORONOI + #pragma shader_feature_local _SHARED_UV + #pragma shader_feature_local _ _VAT _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _ _VAT_HOUDINI _VAT_TYFLOW + #pragma shader_feature_local_vertex _ _HOUDINI_VAT_SOFTBODY _HOUDINI_VAT_RIGIDBODY _HOUDINI_VAT_DYNAMIC_REMESH _HOUDINI_VAT_PARTICLE_SPRITE + #pragma shader_feature_local_vertex _ _TYFLOW_VAT_ABSOLUTE _TYFLOW_VAT_RELATIVE _TYFLOW_VAT_SKIN_R _TYFLOW_VAT_SKIN_PR _TYFLOW_VAT_SKIN_PRSAVE _TYFLOW_VAT_SKIN_PRSXYZ + #pragma shader_feature_local _ALPHATEST_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local_vertex _VERTEX_OFFSET + #pragma shader_feature_local_vertex _VERTEX_OFFSET_MASKMAP + #pragma shader_feature_local _UNSCALETIME + #pragma shader_feature_local _SCRIPTABLETIME + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/NBShaderForwardPass.hlsl" + + ENDHLSL + } + + Pass + { + Name "ShadowCaster" + Tags + { + "LightMode" = "ShadowCaster" + } + + Blend One Zero + ZWrite On + ZTest LEqual + ColorMask 0 + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + #define _FX_LIGHT_MODE_UNLIT + #define NB_SHADOW_CASTER_PASS + + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _MASKMAP2_ON + #pragma shader_feature_local _MASKMAP3_ON + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISE_MASKMAP + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _DISSOLVE_MASK + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _PROGRAM_NOISE_SIMPLE + #pragma shader_feature_local _PROGRAM_NOISE_VORONOI + #pragma shader_feature_local _SHARED_UV + #pragma shader_feature_local _ _VAT _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _ _VAT_HOUDINI _VAT_TYFLOW + #pragma shader_feature_local_vertex _ _HOUDINI_VAT_SOFTBODY _HOUDINI_VAT_RIGIDBODY _HOUDINI_VAT_DYNAMIC_REMESH _HOUDINI_VAT_PARTICLE_SPRITE + #pragma shader_feature_local_vertex _ _TYFLOW_VAT_ABSOLUTE _TYFLOW_VAT_RELATIVE _TYFLOW_VAT_SKIN_R _TYFLOW_VAT_SKIN_PR _TYFLOW_VAT_SKIN_PRSAVE _TYFLOW_VAT_SKIN_PRSXYZ + #pragma shader_feature_local _ALPHATEST_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local_vertex _VERTEX_OFFSET + #pragma shader_feature_local_vertex _VERTEX_OFFSET_MASKMAP + #pragma shader_feature_local _UNSCALETIME + #pragma shader_feature_local _SCRIPTABLETIME + + #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/NBShaderForwardPass.hlsl" + + ENDHLSL + } + + // ------------------------------------------------------------------ + // Distort pass. + Pass + { + Name "NBCameraOpaqueDistortPass" + Tags{ + "LightMode" = "NBCameraOpaqueDistortPass" + } //Queue设置是希望特效渲染在场景透明物体前面 + Blend SrcAlpha OneMinusSrcAlpha + offset [_offsetFactor], [_offsetUnits] + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + //20240228 target3.0 顶点着色器限制16个输出。提高版本 + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + // ------------------------------------- + // Material Keywords + + #include_with_pragmas "Packages/com.xuanxuan.nb.fx/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl" + + #define _SCREEN_DISTORT_MODE + #define _CAMERA_OPAQUE_DISTORT_PASS + #pragma shader_feature_local _ _DISTORT_REFRACTION + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _MASKMAP2_ON + #pragma shader_feature_local _MASKMAP3_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISE_MASKMAP + #pragma shader_feature_local_fragment _CHROMATIC_ABERRATION + //#pragma shader_feature_local _EMISSION //流光 + // #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _DISSOLVE_MASK + #pragma shader_feature_local_fragment _DISSOLVE_RAMP + #pragma shader_feature_local_fragment _DISSOLVE_RAMP_MAP + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _PROGRAM_NOISE_SIMPLE + #pragma shader_feature_local _PROGRAM_NOISE_VORONOI + // #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + // #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local _SHARED_UV//公共UV + + + + // #pragma multi_compile_local _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //UI 2D遮罩 + // #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local_vertex _VERTEX_OFFSET + #pragma shader_feature_local_vertex _VERTEX_OFFSET_MASKMAP + + #pragma shader_feature_local_fragment _FRESNEL + + + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + + #pragma shader_feature_local _DEPTH_DECAL + #pragma shader_feature_local _DEPTH_OUTLINE + #pragma shader_feature_local _DISTANCE_FADE + // #pragma shader_feature_local _PARALLAX_MAPPING + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + // #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT _FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT + #pragma shader_feature_local _ _NORMALMAP + // #pragma shader_feature_local _ _MATCAP + // #pragma shader_feature_local _ _SPECULAR_COLOR + // #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera + // depth texture. + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/NBShaderForwardPass.hlsl" + + + ENDHLSL + + } + +// ------------------------------------------------------------------ + // Distort pass. + Pass + { + Name "NBDeferredDistortPass" + Tags{ + "LightMode" = "NBDeferredDistortPass" + } //Queue设置是希望特效渲染在场景透明物体前面 + Blend SrcAlpha OneMinusSrcAlpha + offset [_offsetFactor], [_offsetUnits] + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + //20240228 target3.0 顶点着色器限制16个输出。提高版本 + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + // ------------------------------------- + // Material Keywords + + #include_with_pragmas "Packages/com.xuanxuan.nb.fx/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl" + + #define _SCREEN_DISTORT_MODE + #define _DEFERRED_DISTORT_PASS + #pragma shader_feature_local _ _DISTORT_REFRACTION + + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _MASKMAP2_ON + #pragma shader_feature_local _MASKMAP3_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISE_MASKMAP + #pragma shader_feature_local_fragment _CHROMATIC_ABERRATION + //#pragma shader_feature_local _EMISSION //流光 + // #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _DISSOLVE_MASK + #pragma shader_feature_local_fragment _DISSOLVE_RAMP + #pragma shader_feature_local_fragment _DISSOLVE_RAMP_MAP + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _PROGRAM_NOISE_SIMPLE + #pragma shader_feature_local _PROGRAM_NOISE_VORONOI + // #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + // #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local _SHARED_UV//公共UV + + + + // #pragma multi_compile_local _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //UI 2D遮罩 + // #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local_vertex _VERTEX_OFFSET + #pragma shader_feature_local_vertex _VERTEX_OFFSET_MASKMAP + + #pragma shader_feature_local_fragment _FRESNEL + + + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _FLIPBOOKBLENDING_ON + #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + + #pragma shader_feature_local _DEPTH_DECAL + #pragma shader_feature_local _DEPTH_OUTLINE + #pragma shader_feature_local _DISTANCE_FADE + // #pragma shader_feature_local _PARALLAX_MAPPING + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + // #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT _FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT + #pragma shader_feature_local _ _NORMALMAP + // #pragma shader_feature_local _ _MATCAP + // #pragma shader_feature_local _ _SPECULAR_COLOR + // #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera + // depth texture. + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + #include "HLSL/NBShaderForwardPass.hlsl" + + + ENDHLSL + + } + + // ------------------------------------------------------------------ + // Forward pass. + Pass + { + Name "Universal2D" + Tags + { + "LightMode" = "Universal2D" + } //Queue设置是希望特效渲染在场景透明物体前面 + offset [_offsetFactor], [_offsetUnits] + Cull[_Cull] + + HLSLPROGRAM + #define PARTICLE + //20240228 target3.0 顶点着色器限制16个输出。提高版本 + #if defined ( SHADER_API_GLES)||defined(SHADER_API_GLES3) + #pragma target 3.0 + #else + #pragma target 4.5 + #endif + + // ------------------------------------- + // Material Keywords + + #include_with_pragmas "Packages/com.xuanxuan.nb.fx/NBShaders2/Shader/HLSL/NBShaderDebugPragmas.hlsl" + + #pragma shader_feature_local _ _SCREEN_DISTORT_MODE + #pragma shader_feature_local _ _MASKMAP_ON + #pragma shader_feature_local _MASKMAP2_ON + #pragma shader_feature_local _MASKMAP3_ON + // #pragma shader_feature_local _MASKMAP + // #pragma shader_feature_local _MASKMAP2 + //#pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISEMAP + #pragma shader_feature_local _NOISE_MASKMAP + #pragma shader_feature_local_fragment _CHROMATIC_ABERRATION + //#pragma shader_feature_local _EMISSION //流光 + #pragma shader_feature_local _EMISSION + //#pragma shader_feature_local _ _DISSOLVE //溶解 + #pragma shader_feature_local _DISSOLVE + #pragma shader_feature_local _DISSOLVE_MASK + #pragma shader_feature_local_fragment _DISSOLVE_RAMP + #pragma shader_feature_local_fragment _DISSOLVE_RAMP_MAP + #pragma shader_feature_local _PROGRAM_NOISE + #pragma shader_feature_local _PROGRAM_NOISE_SIMPLE + #pragma shader_feature_local _PROGRAM_NOISE_VORONOI + #pragma shader_feature_local _COLORMAPBLEND//颜色渐变 + #pragma shader_feature_local _COLOR_RAMP//颜色映射 + #pragma shader_feature_local_fragment _COLOR_RAMP_MAP + #pragma shader_feature_local _SHARED_UV//公共UV + + + + #pragma multi_compile_local _ UNITY_UI_CLIP_RECT _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS //UI 2D遮罩 + // #pragma shader_feature_local _ _CH_XIANXING _CH_JINGXIANG _CH_SELF //线性擦除 径向擦除 mask擦除 + #pragma shader_feature_local _PARCUSTOMDATA_ON + + //用于特效层关键字 + // #pragma shader_feature_local _UIEFFECT_ON + #pragma shader_feature_local _CUSTOM_LOCAL_TRANSFORM + #pragma shader_feature_local_vertex _VERTEX_OFFSET + #pragma shader_feature_local_vertex _VERTEX_OFFSET_MASKMAP + + #pragma shader_feature_local_fragment _FRESNEL + + + // #pragma multi_compile _ _UIPARTICLE_ON//用于UIParticle组件动态更改参数//暂时注释掉,觉得没什么意义 + #pragma multi_compile _ SOFT_UI_FRAME EVALUATE_SH_MIXED EVALUATE_SH_VERTEX//用于UI软蒙版 + // ------------------------------------- + // Particle Keywords + #pragma shader_feature_local _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON //设置alpah Add 。。组合 + #pragma shader_feature_local _ALPHATEST_ON + //#pragma shader_feature_local _ _COLOROVERLAY_ON _COLORCOLOR_ON _COLORADDSUBDIFF_ON //粒子颜色和材质颜色的混合运算 暂时先不要了 + #pragma shader_feature_local _FLIPBOOKBLENDING_ON + // #pragma shader_feature_local _SOFTPARTICLES_ON + // #pragma shader_feature_local _OCCLUDEOPACITY_ON + // #pragma shader_feature_local _ _SATURABILITY_ON + + //UnscaleTime用于接收项目传的公开不受缩放影响的Time值 + #pragma shader_feature_local _UNSCALETIME + //scriptableTime用于程序每帧传值 + #pragma shader_feature_local _SCRIPTABLETIME + //#pragma shader_feature_local _DISTORTION_ON + + // #pragma shader_feature_local _DEPTH_DECAL + // #pragma shader_feature_local _PARALLAX_MAPPING + + #pragma shader_feature_local _STENCIL_WITHOUT_PLAYER + + //LIGHTING + // #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT _FX_LIGHT_MODE_BLINN_PHONG _FX_LIGHT_MODE_HALF_LAMBERT _FX_LIGHT_MODE_PBR _FX_LIGHT_MODE_SIX_WAY + #pragma shader_feature_local _FX_LIGHT_MODE_UNLIT + #pragma shader_feature_local _ _NORMALMAP + // #pragma shader_feature_local _ _MATCAP + // #pragma shader_feature_local _ _SPECULAR_COLOR + // #pragma shader_feature_local _ VFX_SIX_WAY_ABSORPTION + + // ------------------------------------- + // Unity defined keywords + // 之后进行优化时再说。 + #pragma multi_compile_fog + // #define FOG_EXP2 1 + + #pragma vertex vertParticleUnlit + #pragma fragment fragParticleUnlit + + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + // The DeclareDepthTexture.hlsl file contains utilities for sampling the Camera + // depth texture. + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" + + #include "../../XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl" + + #include "HLSL/NBShaderForwardPass.hlsl" + + + ENDHLSL + + } + } + + CustomEditor "NBShaderEditor.NBShaderGUI" +} diff --git a/Packages/NB_FX/NBShaders2/Shader/NBShader.shader.meta b/Packages/NB_FX/NBShaders2/Shader/NBShader.shader.meta new file mode 100644 index 00000000..0a296395 --- /dev/null +++ b/Packages/NB_FX/NBShaders2/Shader/NBShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7787bfdacec31472ca6644d6e3616bd4 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility.meta b/Packages/NB_FX/XuanXuanRenderUtility.meta new file mode 100644 index 00000000..5cdb23d4 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 29374ac7fcbcd9742920d575923f43d4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor.meta new file mode 100644 index 00000000..a0f47e55 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fd758a702a9040fcb8614b232817cff9 +timeCreated: 1721290722 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/AnimationSheetHelperEditor.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/AnimationSheetHelperEditor.cs new file mode 100644 index 00000000..f52bce19 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/AnimationSheetHelperEditor.cs @@ -0,0 +1,146 @@ +using UnityEditor; +using UnityEngine; + +[CustomEditor(typeof(AnimationSheetHelper))] +public class AnimationSheetHelperEditor : Editor +{ + SerializedProperty isParticleBaseShader; + SerializedProperty isPostProcessShader; + SerializedProperty postProcessingController; + SerializedProperty propertyName; + + SerializedProperty xSize; + SerializedProperty ySize; + + SerializedProperty manualPlay; + SerializedProperty manualPlayePos; + SerializedProperty speed; + + SerializedProperty scaleOffset; + SerializedProperty mat; + SerializedProperty frameIndex; + SerializedProperty frameCount; + + private AnimationSheetHelper _target; + + void OnEnable() + { + _target = (AnimationSheetHelper)target; + + isParticleBaseShader = serializedObject.FindProperty("isParticleBaseShader"); + // isPostProcessShader = serializedObject.FindProperty("isPostProcessShader"); + // postProcessingController = serializedObject.FindProperty("postProcessingController"); + propertyName = serializedObject.FindProperty("propertyName"); + + xSize = serializedObject.FindProperty("xSize"); + ySize = serializedObject.FindProperty("ySize"); + + manualPlay = serializedObject.FindProperty("manualPlay"); + manualPlayePos = serializedObject.FindProperty("manualPlayePos"); + speed = serializedObject.FindProperty("speed"); + + scaleOffset = serializedObject.FindProperty("scaleOffset"); + mat = serializedObject.FindProperty("mat"); + frameIndex = serializedObject.FindProperty("frameIndex"); + frameCount = serializedObject.FindProperty("frameCount"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + DrawShaderSection(); + EditorGUILayout.Space(5); + DrawAnimationSection(); + EditorGUILayout.Space(5); + DrawRuntimeInfo(); + EditorGUILayout.Space(8); + DrawInitButton(); + + serializedObject.ApplyModifiedProperties(); + } + + #region Sections + + void DrawShaderSection() + { + EditorGUILayout.LabelField("Shader 设置", EditorStyles.boldLabel); + + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(isParticleBaseShader, new GUIContent("使用 NB Shader")); + if (EditorGUI.EndChangeCheck()) + { + serializedObject.ApplyModifiedProperties(); + _target.InitParticleBaseShaderToggle(); + EditorUtility.SetDirty(_target); + } + + // EditorGUI.BeginChangeCheck(); + // EditorGUILayout.PropertyField(isPostProcessShader, new GUIContent("使用 后处理扭曲")); + // if (EditorGUI.EndChangeCheck()) + // { + // serializedObject.ApplyModifiedProperties(); + // // _target.InitPostProcessToggle(); + // EditorUtility.SetDirty(_target); + // } + + // if (isPostProcessShader.boolValue) + // { + // GUI.enabled = false; + // EditorGUILayout.PropertyField(postProcessingController); + // GUI.enabled = true; + // } + + EditorGUILayout.PropertyField(propertyName, new GUIContent("Shader 属性名")); + } + + void DrawAnimationSection() + { + EditorGUILayout.LabelField("序列帧设置", EditorStyles.boldLabel); + + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(xSize, new GUIContent("横向帧数量")); + EditorGUILayout.PropertyField(ySize, new GUIContent("纵向帧数量")); + if (EditorGUI.EndChangeCheck()) + { + serializedObject.ApplyModifiedProperties(); + _target.Init(); + EditorUtility.SetDirty(_target); + } + + EditorGUILayout.Space(4); + EditorGUILayout.PropertyField(manualPlay, new GUIContent("手动控制播放")); + + if (manualPlay.boolValue) + { + EditorGUILayout.PropertyField(manualPlayePos, new GUIContent("手动播放位置")); + } + else + { + EditorGUILayout.PropertyField(speed, new GUIContent("播放速度 fps")); + } + } + + void DrawRuntimeInfo() + { + EditorGUILayout.LabelField("运行时信息", EditorStyles.boldLabel); + + GUI.enabled = false; + EditorGUILayout.PropertyField(scaleOffset, new GUIContent("Tiling Offset")); + EditorGUILayout.PropertyField(mat, new GUIContent("Material")); + EditorGUILayout.PropertyField(frameIndex); + EditorGUILayout.PropertyField(frameCount); + GUI.enabled = true; + } + + void DrawInitButton() + { + if (GUILayout.Button("初始化", GUILayout.Height(28))) + { + _target.Init(); + EditorUtility.SetDirty(_target); + } + } + + #endregion +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/AnimationSheetHelperEditor.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/AnimationSheetHelperEditor.cs.meta new file mode 100644 index 00000000..efe4e8d3 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/AnimationSheetHelperEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2e1a5d6748bd4515869cb9c6ebd2b548 +timeCreated: 1769260616 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/BinaryIntAttribute.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/BinaryIntAttribute.cs new file mode 100644 index 00000000..c51b59b1 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/BinaryIntAttribute.cs @@ -0,0 +1,103 @@ +using UnityEditor; +using UnityEngine; +using System; + +namespace NBShaderEditor +{ + public class BinaryIntAttribute : PropertyAttribute + { + public int binaryBits; + public bool showInputFiled; + public int tabNums; + + + public BinaryIntAttribute(int Bits = 32, bool showInput = false, int tab = 0) + { + binaryBits = Bits; + showInputFiled = showInput; + tabNums = tab; + } + } + + [CustomPropertyDrawer(typeof(BinaryIntAttribute))] + public class BinaryIntDrawer : PropertyDrawer + { + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + + GUIStyle richTextStyle = EditorStyles.label; + richTextStyle.richText = true; + BinaryIntAttribute binaryIntAttribute = (BinaryIntAttribute)attribute; + // int value = property.intValue; + // int largestBit = 0; + // for (int i = 0; i < 32; i++) + // { + // if ((~value & (1 << i)) == 0) + // { + // largestBit = i; + // } + // } + // + // int addZeroCount = 0; + // if (largestBit < binaryIntAttribute.binaryBits) + // { + // addZeroCount = binaryIntAttribute.binaryBits - largestBit - 1; + // } + // + // string addZeroString = ""; + // for (int i = 0; i < addZeroCount; i++) + // { + // addZeroString += "0"; + // } + // string binary = addZeroString+Convert.ToString(property.intValue, 2); + string binary = DrawBinaryInt(property.intValue, binaryIntAttribute.binaryBits); + + string tabs = ""; + for (int i = 0; i < binaryIntAttribute.tabNums; i++) + { + tabs += "\t"; + } + + if (binaryIntAttribute.showInputFiled) + { + string labelText = property.displayName + tabs + "" + binary + ""; + Rect intRect = EditorGUI.PrefixLabel(position, new GUIContent(labelText), richTextStyle); + property.intValue = EditorGUI.IntField(intRect, property.intValue); + } + else + { + EditorGUILayout.LabelField(property.displayName + tabs); + EditorGUILayout.LabelField(binary); + } + } + + public static string DrawBinaryInt(int value, int binaryBits) + { + int largestBit = 0; + for (int i = 0; i < 32; i++) + { + if ((~value & (1 << i)) == 0) + { + largestBit = i; + } + } + + int addZeroCount = 0; + if (largestBit < binaryBits) + { + addZeroCount = binaryBits - largestBit - 1; + } + + string addZeroString = ""; + for (int i = 0; i < addZeroCount; i++) + { + addZeroString += "0"; + } + + string binary = addZeroString + Convert.ToString(value, 2); + return binary; + } + } +} + \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/BinaryIntAttribute.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/BinaryIntAttribute.cs.meta new file mode 100644 index 00000000..1d933dac --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/BinaryIntAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4517deaf5f31a5848b6a58304d1f516f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/GradientRefletctionHelper.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/GradientRefletctionHelper.cs new file mode 100644 index 00000000..be2cfde0 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/GradientRefletctionHelper.cs @@ -0,0 +1,253 @@ +using System; +using System.Reflection; +using UnityEngine; + +namespace NBShaderEditor +{ +//因为GradientPicker窗口,在窗口打开时使用的是Gradient对象的Cache。 +//如果有Undo操作,导致MaterialProperty更新了,但Gradient却更新不到ColorPicer里。所以在这里进行强制更新。 +//后续需要强制更新Picker的时候,也可以用这里。 +//DeepSeek写的。谨慎用。 + public static class GradientReflectionHelper + { + #region GradientPicker 相关 + + private static Type _gradientPickerType; + + // SetCurrentGradient 方法 + private static MethodInfo _setGradientMethod; + private static Action _setGradientDelegate; + + // RefreshGradientData 方法 + private static MethodInfo _refreshMethod; + private static Action _refreshDelegate; + + #endregion + + #region GradientPreviewCache 相关 + + private static Type _gradientCacheType; + private static MethodInfo _clearCacheMethod; + private static Action _clearCacheDelegate; + + #endregion + + // 初始化状态 + private static bool _initialized; + private static bool _isValid; + private static readonly object _initLock = new object(); + + #region 公共API + + [System.Diagnostics.Conditional("UNITY_EDITOR")] + public static void SetCurrentGradient(Gradient gradient) + { + ExecuteAction(() => + { + if (_setGradientDelegate != null) + _setGradientDelegate(gradient); + else if (_setGradientMethod != null) + _setGradientMethod.Invoke(null, new object[] { gradient }); + }, "SetCurrentGradient"); + } + + [System.Diagnostics.Conditional("UNITY_EDITOR")] + public static void RefreshGradientData() + { + ExecuteAction(() => + { + if (_refreshDelegate != null) + _refreshDelegate(); + else if (_refreshMethod != null) + _refreshMethod.Invoke(null, null); + }, "RefreshGradientData"); + } + + [System.Diagnostics.Conditional("UNITY_EDITOR")] + public static void ClearGradientCache() + { + ExecuteAction(() => + { + if (_clearCacheDelegate != null) + _clearCacheDelegate(); + else if (_clearCacheMethod != null) + _clearCacheMethod.Invoke(null, null); + }, "ClearGradientCache"); + } + + #endregion + + #region 核心实现 + + private static void ExecuteAction(Action action, string methodName) + { + if (!Application.isEditor) return; + + EnsureInitialized(); + if (!_isValid) return; + + try + { + action?.Invoke(); + } + catch (Exception ex) + { + Debug.LogError($"[GradientReflection] {methodName} failed: {ex.Message}"); + // 可选择性地禁用后续调用 + // _isValid = false; + } + } + + private static void EnsureInitialized() + { + if (_initialized) return; + + lock (_initLock) + { + if (_initialized) return; + + try + { + // 1. 初始化 GradientPicker 类型 + _gradientPickerType = Type.GetType("UnityEditor.GradientPicker, UnityEditor"); + if (_gradientPickerType != null) + { + // 初始化 SetCurrentGradient + _setGradientMethod = GetStaticMethod( + _gradientPickerType, + "SetCurrentGradient", + new[] { typeof(Gradient) } + ); + if (_setGradientMethod != null) + { + _setGradientDelegate = CreateActionDelegate(_setGradientMethod); + } + + // 初始化 RefreshGradientData + _refreshMethod = GetStaticMethod( + _gradientPickerType, + "RefreshGradientData", + Type.EmptyTypes + ); + if (_refreshMethod != null) + { + _refreshDelegate = CreateActionDelegate(_refreshMethod); + } + } + else + { + Debug.LogWarning("[GradientReflection] GradientPicker type not found"); + } + + // 2. 初始化 GradientPreviewCache + _gradientCacheType = Type.GetType("UnityEditorInternal.GradientPreviewCache, UnityEditor"); + if (_gradientCacheType != null) + { + _clearCacheMethod = GetStaticMethod( + _gradientCacheType, + "ClearCache", + Type.EmptyTypes + ); + if (_clearCacheMethod != null) + { + _clearCacheDelegate = CreateActionDelegate(_clearCacheMethod); + } + } + else + { + Debug.LogWarning("[GradientReflection] GradientPreviewCache type not found"); + } + + // 3. 验证初始化状态 + _isValid = (_setGradientMethod != null || _refreshMethod != null) && + _clearCacheMethod != null; + + if (!_isValid) + { + Debug.LogWarning($"[GradientReflection] Initialization incomplete. " + + $"SetCurrentGradient: {(_setGradientMethod != null ? "OK" : "Missing")}, " + + $"RefreshGradientData: {(_refreshMethod != null ? "OK" : "Missing")}, " + + $"ClearCache: {(_clearCacheMethod != null ? "OK" : "Missing")}"); + } + else + { + // Debug.Log("[GradientReflection] Initialized successfully"); + } + } + catch (Exception e) + { + Debug.LogError($"[GradientReflection] Initialization failed: {e}"); + _isValid = false; + } + finally + { + _initialized = true; + } + } + } + + private static MethodInfo GetStaticMethod(Type type, string methodName, Type[] parameterTypes) + { + if (type == null) return null; + + return type.GetMethod( + methodName, + BindingFlags.Public | BindingFlags.Static, + null, + parameterTypes, + null + ); + } + + private static Action CreateActionDelegate(MethodInfo method) + { + try + { + return (Action)Delegate.CreateDelegate(typeof(Action), method); + } + catch (Exception ex) + { + Debug.LogWarning($"[GradientReflection] Failed to create delegate for {method.Name}: {ex.Message}"); + return null; + } + } + + private static Action CreateActionDelegate(MethodInfo method) + { + try + { + return (Action)Delegate.CreateDelegate(typeof(Action), method); + } + catch (Exception ex) + { + Debug.LogWarning($"[GradientReflection] Failed to create delegate for {method.Name}: {ex.Message}"); + return null; + } + } + + #endregion + + #region 辅助功能 + + /// + /// 检查是否所有反射方法都可用 + /// + public static bool IsFullySupported => _isValid; + + /// + /// 获取反射初始化状态 + /// + public static string GetReflectionStatus() + { + if (!_initialized) return "Not Initialized"; + + return $"GradientPicker: {(_gradientPickerType != null ? "Found" : "Missing")}\n" + + $"- SetCurrentGradient: {(_setGradientMethod != null ? "OK" : "Missing")}\n" + + $"- RefreshGradientData: {(_refreshMethod != null ? "OK" : "Missing")}\n" + + $"GradientPreviewCache: {(_gradientCacheType != null ? "Found" : "Missing")}\n" + + $"- ClearCache: {(_clearCacheMethod != null ? "OK" : "Missing")}"; + } + + #endregion + } +} \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/GradientRefletctionHelper.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/GradientRefletctionHelper.cs.meta new file mode 100644 index 00000000..1b399df3 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/GradientRefletctionHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ebe6cf7ae30f4357bae940f8ce409628 +timeCreated: 1753589587 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/MaterialPropertyAgentInspector.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/MaterialPropertyAgentInspector.cs new file mode 100644 index 00000000..3a7ff1d3 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/MaterialPropertyAgentInspector.cs @@ -0,0 +1,261 @@ +using UnityEditor; +using UnityEngine; +using UnityEditor.Experimental.GraphView; +using System; +using NBShader; + +namespace NBShaderEditor +{ +// #if UNITY_EDITOR + [CustomEditor(typeof(MaterialPropertyAgent))] + public class MaterialPropertyAgentInspector : UnityEditor.Editor + { + private MaterialPropertyAgent agent; + + private void OnEnable() + { + agent = (MaterialPropertyAgent)target; + } + + private GUIContent materialIndexContent = new GUIContent("材质序号:", "只有模型模式下需要使用,谨慎修改"); + + public override void OnInspectorGUI() + { + serializedObject.Update(); + EditorGUI.BeginChangeCheck(); + if (!agent.isGetByComponet) + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("customRenderer"), + new GUIContent("指定Renderer")); + } + + if (agent.isRendererMode) + { + EditorGUILayout.BeginHorizontal(); + int lastIndex = agent.materialIndex; + agent.materialIndex = EditorGUILayout.IntField(materialIndexContent, agent.materialIndex); + if (lastIndex != agent.materialIndex) + { + agent.initMatAndShaderByMaterialIndexChange(); + } + + EditorGUILayout.LabelField("材质名:" + agent.mat.name + "\t" + "Shader名:" + agent.shader.name); + EditorGUILayout.EndHorizontal(); + } + + DrawPropertyData(ref agent.data0, "Data0", serializedObject.FindProperty("data0")); + DrawPropertyData(ref agent.data1, "Data1", serializedObject.FindProperty("data1")); + DrawPropertyData(ref agent.data2, "Data2", serializedObject.FindProperty("data2")); + DrawPropertyData(ref agent.data3, "Data3", serializedObject.FindProperty("data3")); + DrawPropertyData(ref agent.data4, "Data4", serializedObject.FindProperty("data4")); + DrawPropertyData(ref agent.data5, "Data5", serializedObject.FindProperty("data5")); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("添加")) + { + agent.addProperteData(); + } + + if (GUILayout.Button("全部删除")) + { + agent.removeAllProperty(); + } + + EditorGUILayout.EndHorizontal(); + serializedObject.ApplyModifiedProperties(); + if (EditorGUI.EndChangeCheck()) + { + PrefabUtility.RecordPrefabInstancePropertyModifications(agent); + if (!agent.isGetByComponet && agent.mat) + { + if (matEditor) DestroyImmediate(matEditor); + matEditor = (MaterialEditor)CreateEditor(agent.mat); + } + } + + if (!agent.isGetByComponet && agent.mat) + { + DrawMaterialInspector(matEditor, agent.mat); + } + } + + void DrawPropertyData(ref MaterialPropertyAgent.PropertyData data, string dataLabel, + SerializedProperty property) + { + EditorGUI.BeginProperty(EditorGUILayout.GetControlRect(false, 0f), GUIContent.none, property); + if (data.isActive) + { + EditorGUILayout.LabelField(dataLabel, EditorStyles.boldLabel); + + EditorGUI.indentLevel++; + + EditorGUILayout.BeginHorizontal(); + float originLabelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 80; + // data.index = EditorGUILayout.Popup("属性名:", data.index, agent.shaderPropNameArr); + // data.index = EditorGUILayout.Popup("属性名:", data.index, agent.shaderPropDescripArr); + // string dataDesript = data.descripName; + if (GUILayout.Button(data.descripName, EditorStyles.popup)) + { + int dataIndexInAgent = data.dataIndexInAgent; + + StringListSerchProvider provider = ScriptableObject.CreateInstance(); + provider.Initialize(agent.shaderPropDescripsForSerch, (x) => + { + if (x != null) + { + AfterShaderPropSerch(dataIndexInAgent, x); + } + }); + SearchWindow.Open(new SearchWindowContext(GUIUtility.GUIToScreenPoint(Event.current.mousePosition)), + provider); + // SearchWindow.Open(new SearchWindowContext(GUIUtility.GUIToScreenPoint(Event.current.mousePosition)), + // new StringListSerchProvider(agent.shaderPropDescripsForSerch, (x) => + // { + // if (x != null) + // { + // AfterShaderPropSerch(dataIndexInAgent,x); + // } + // })); + } + + + + EditorGUILayout.LabelField("属性类型:", data.type.ToString()); + + EditorGUILayout.EndHorizontal(); + EditorGUIUtility.labelWidth = originLabelWidth; + switch (data.type) + { + case MaterialPropertyAgent.shaderPropertyType.Color: + SerializedProperty colorProp = property.FindPropertyRelative("colorValue"); + if (data.descripName.ToLower().Contains("hdr")) + { + colorProp.colorValue = EditorGUILayout.ColorField(new GUIContent(data.propName + " :"), + colorProp.colorValue, true, true, true); + } + else + { + colorProp.colorValue = + EditorGUILayout.ColorField(data.propName + " :", colorProp.colorValue); + } + + break; + case MaterialPropertyAgent.shaderPropertyType.Vector: + case MaterialPropertyAgent.shaderPropertyType.TexEnv: + SerializedProperty vecProp = property.FindPropertyRelative("vecValue"); + if (data.type == MaterialPropertyAgent.shaderPropertyType.Vector) + { + vecProp.vector4Value = + EditorGUILayout.Vector4Field(data.propName + " :", vecProp.vector4Value); + } + else if (data.type == MaterialPropertyAgent.shaderPropertyType.TexEnv) + { + vecProp.vector4Value = + EditorGUILayout.Vector4Field(data.propName + ":", vecProp.vector4Value); + + } + + break; + case MaterialPropertyAgent.shaderPropertyType.Float: + case MaterialPropertyAgent.shaderPropertyType.Range: + SerializedProperty floatProp = property.FindPropertyRelative("floatValue"); + if (data.type == MaterialPropertyAgent.shaderPropertyType.Float) + { + floatProp.floatValue = + EditorGUILayout.FloatField(data.propName + ":", floatProp.floatValue); + } + else if (data.type == MaterialPropertyAgent.shaderPropertyType.Range) + { + floatProp.floatValue = EditorGUILayout.Slider(data.propName + ":", floatProp.floatValue, + data.rangMin, data.rangMax); + + } + + break; + + } + + if (GUILayout.Button("删除", new[] { GUILayout.Width(200) })) + { + data.isActive = false; + } + + EditorGUI.indentLevel--; + // EditorGUILayout.Space(); + } + + EditorGUI.EndProperty(); + } + + //因为Action不能有Ref。所以有了这个丑陋的HardCode + public void AfterShaderPropSerch(int dataIndexInAgent, string propertyDesrpt) + { + switch (dataIndexInAgent) + { + case 0: + AfterShaderPropSerch(ref agent.data0, propertyDesrpt); + break; + case 1: + AfterShaderPropSerch(ref agent.data1, propertyDesrpt); + break; + case 2: + AfterShaderPropSerch(ref agent.data2, propertyDesrpt); + break; + case 3: + AfterShaderPropSerch(ref agent.data3, propertyDesrpt); + break; + case 4: + AfterShaderPropSerch(ref agent.data4, propertyDesrpt); + break; + case 5: + AfterShaderPropSerch(ref agent.data5, propertyDesrpt); + break; + + + } + } + + public void AfterShaderPropSerch(ref MaterialPropertyAgent.PropertyData data, string propertyDesrpt) + { + int preservedIndex = data.index; + // string propname = data.propName; + data.index = Array.FindIndex(agent.shaderPropDescripArr, x => x.Equals(propertyDesrpt)); + // Debug.Log(); + if (preservedIndex != data.index) //证明用户进行了更改 + { + if (!agent.isCanUsedIndex(data.index)) + { + //TODO给一个报错提示 + Debug.LogError("材质属性已经存在:" + agent.shader.GetPropertyDescription(data.index)); + data.index = agent.getCanUsedIndex(); + } + + //此处进行内容刷新 + data.setValueByPropChange(); + } + } + + private MaterialEditor matEditor; + + void DrawMaterialInspector(MaterialEditor editor, Material mat) + { + if (editor != null && mat != null) + { + // Draw the material's foldout and the material shader field + // Required to call _materialEditor.OnInspectorGUI (); + editor.DrawHeader(); + // We need to prevent the user to edit Unity default materials + bool isDefaultMaterial = !AssetDatabase.GetAssetPath(mat).StartsWith("Assets"); + using (new EditorGUI.DisabledGroupScope(isDefaultMaterial)) + { + + // Draw the material properties + // Works only if the foldout of _materialEditor.DrawHeader () is open + editor.OnInspectorGUI(); + } + } + } + + } +} +// #endif diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/MaterialPropertyAgentInspector.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/MaterialPropertyAgentInspector.cs.meta new file mode 100644 index 00000000..94c4f3b2 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/MaterialPropertyAgentInspector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b9544bec10c84ecca289bece4a630d65 +timeCreated: 1702126025 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/MeshUIInspector.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/MeshUIInspector.cs new file mode 100644 index 00000000..f5693af1 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/MeshUIInspector.cs @@ -0,0 +1,383 @@ +using Unity.Collections; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; +using NBShader; + +namespace NBShaderEditor +{ + [CustomEditor(typeof(MeshUI))] + [CanEditMultipleObjects] + public class MeshUIInspector : Editor + { + private SerializedProperty _meshProp; + private SerializedProperty _subMeshMaterialsProp; + private SerializedProperty _colorProp; + private SerializedProperty _raycastTargetProp; + private SerializedProperty _maskableProp; + + private void OnEnable() + { + _meshProp = serializedObject.FindProperty("mesh"); + _subMeshMaterialsProp = serializedObject.FindProperty("subMeshMaterials"); + _colorProp = serializedObject.FindProperty("m_Color"); + _raycastTargetProp = serializedObject.FindProperty("m_RaycastTarget"); + _maskableProp = serializedObject.FindProperty("m_Maskable"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + DrawMeshSection(); + EditorGUILayout.Space(); + DrawSubMeshMaterials(); + EditorGUILayout.Space(); + DrawUGUISection(); + EditorGUILayout.Space(); + DrawMeshInfo(); + + serializedObject.ApplyModifiedProperties(); + } + + private void DrawMeshSection() + { + EditorGUILayout.LabelField("Mesh", EditorStyles.boldLabel); + + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(_meshProp, new GUIContent("模型")); + if (EditorGUI.EndChangeCheck()) + { + serializedObject.ApplyModifiedProperties(); + SyncSlotsToMesh(); + serializedObject.Update(); + } + + DrawBakeMeshSection(); + } + + private void DrawSubMeshMaterials() + { + Mesh mesh = _meshProp.objectReferenceValue as Mesh; + int targetSize = mesh != null ? mesh.subMeshCount : _subMeshMaterialsProp.arraySize; + + EditorGUILayout.LabelField("Mesh Materials", EditorStyles.boldLabel); + + if (mesh != null && _subMeshMaterialsProp.arraySize != targetSize) + { + EditorGUILayout.HelpBox($"当前材质槽位数量为 {_subMeshMaterialsProp.arraySize},Mesh 的 SubMesh 数量为 {targetSize}。更换 Mesh 后会自动同步槽位。", MessageType.Warning); + } + + for (int i = 0; i < _subMeshMaterialsProp.arraySize; i++) + { + SerializedProperty element = _subMeshMaterialsProp.GetArrayElementAtIndex(i); + string label = $"Sub Mesh {i}"; + if (mesh != null && i < mesh.subMeshCount) + { + label += $" ({mesh.GetTopology(i)})"; + } + + EditorGUILayout.PropertyField(element, new GUIContent(label)); + } + } + + private void DrawUGUISection() + { + EditorGUILayout.LabelField("UGUI", EditorStyles.boldLabel); + EditorGUILayout.PropertyField(_colorProp, new GUIContent("颜色")); + EditorGUILayout.PropertyField(_raycastTargetProp, new GUIContent("射线检测")); + EditorGUILayout.PropertyField(_maskableProp, new GUIContent("支持 Mask")); + } + + private void DrawMeshInfo() + { + Mesh mesh = _meshProp.objectReferenceValue as Mesh; + EditorGUILayout.LabelField("信息", EditorStyles.boldLabel); + + if (mesh == null) + { + EditorGUILayout.HelpBox("未指定 Mesh。请先指定一个包含三角形拓扑的模型。", MessageType.Warning); + return; + } + + int subMeshCount = mesh.subMeshCount; + int triangleSubMeshCount = GetTriangleSubMeshCount(mesh); + int vertexCount = mesh.vertexCount; + int indexCount = 0; + + for (int i = 0; i < subMeshCount; i++) + { + if (mesh.GetTopology(i) == MeshTopology.Triangles) + { + indexCount += (int)mesh.GetIndexCount(i); + } + } + + string renderMode = GetRenderModeDescription(mesh); + string info = + $"可读性: {(mesh.isReadable ? "是" : "否")}\n" + + $"顶点数: {vertexCount}\n" + + $"SubMesh 数量: {subMeshCount}\n" + + $"三角形 SubMesh 数量: {triangleSubMeshCount}\n" + + $"三角形索引数: {indexCount}\n" + + $"运行时模式: {renderMode}"; + + EditorGUILayout.HelpBox(info, MessageType.Info); + + if (triangleSubMeshCount == 0) + { + EditorGUILayout.HelpBox("当前 Mesh 不包含可渲染的三角形 SubMesh。", MessageType.Error); + } + else if (triangleSubMeshCount != subMeshCount) + { + EditorGUILayout.HelpBox("当前 Mesh 中存在非三角形拓扑的 SubMesh,运行时会生成 Mesh,并且只渲染三角形 SubMesh。", MessageType.Warning); + } + } + + private string GetRenderModeDescription(Mesh mesh) + { + if (!mesh.isReadable) + { + return "当前 Mesh 不可读,无法渲染"; + } + + if (GetTriangleSubMeshCount(mesh) != mesh.subMeshCount) + { + return "将生成运行时 Mesh(原因:存在非三角形 SubMesh)"; + } + + Color color = _colorProp.colorValue; + if (color != Color.white) + { + return "将生成运行时 Mesh(原因:需要应用 UGUI 颜色)"; + } + + return "将直接使用原始 Mesh"; + } + + private void DrawBakeMeshSection() + { + Mesh mesh = _meshProp.objectReferenceValue as Mesh; + if (mesh == null || mesh.isReadable) + { + return; + } + + EditorGUILayout.HelpBox("当前 Mesh 没有开启 Read/Write,MeshUI 无法直接通过 CanvasRenderer 渲染。请先烘焙出一个可读的 Mesh。", MessageType.Warning); + + if (GUILayout.Button("烘焙只读Mesh")) + { + BakeMeshForTargets(mesh); + } + } + + private int GetTriangleSubMeshCount(Mesh mesh) + { + int count = 0; + for (int i = 0; i < mesh.subMeshCount; i++) + { + if (mesh.GetTopology(i) == MeshTopology.Triangles) + { + count++; + } + } + + return count; + } + + private void BakeMeshForTargets(Mesh sourceMesh) + { + string defaultDirectory = GetDefaultSaveDirectory(sourceMesh); + string defaultName = $"{sourceMesh.name}_MeshUI"; + string assetPath = EditorUtility.SaveFilePanelInProject( + "烘焙 MeshUI Mesh", + defaultName, + "asset", + "请选择烘焙后 Mesh 的保存位置。", + defaultDirectory); + + if (string.IsNullOrEmpty(assetPath)) + { + return; + } + + Mesh bakedMesh = CreateReadableMeshCopy(sourceMesh, System.IO.Path.GetFileNameWithoutExtension(assetPath)); + if (bakedMesh == null) + { + return; + } + + string uniqueAssetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath); + AssetDatabase.CreateAsset(bakedMesh, uniqueAssetPath); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + Mesh bakedAsset = AssetDatabase.LoadAssetAtPath(uniqueAssetPath); + if (bakedAsset == null) + { + Debug.LogError($"无法加载已烘焙的 Mesh 资源: '{uniqueAssetPath}'"); + return; + } + + Undo.RecordObjects(targets, "烘焙 MeshUI Mesh"); + foreach (Object editorTarget in targets) + { + MeshUI meshUI = editorTarget as MeshUI; + if (meshUI == null) + { + continue; + } + + meshUI.Mesh = bakedAsset; + EditorUtility.SetDirty(meshUI); + PrefabUtility.RecordPrefabInstancePropertyModifications(meshUI); + } + + serializedObject.Update(); + SyncSlotsToMesh(); + } + + private string GetDefaultSaveDirectory(Mesh sourceMesh) + { + string sourcePath = AssetDatabase.GetAssetPath(sourceMesh); + if (string.IsNullOrEmpty(sourcePath)) + { + return "Assets"; + } + + string directory = System.IO.Path.GetDirectoryName(sourcePath); + if (string.IsNullOrEmpty(directory)) + { + return "Assets"; + } + + return directory.Replace('\\', '/'); + } + + private static Mesh CreateReadableMeshCopy(Mesh sourceMesh, string newMeshName) + { + using (Mesh.MeshDataArray meshDataArray = MeshUtility.AcquireReadOnlyMeshData(sourceMesh)) + { + if (meshDataArray.Length == 0) + { + Debug.LogError($"无法读取 Mesh 数据: {sourceMesh.name}"); + return null; + } + + Mesh.MeshData meshData = meshDataArray[0]; + Mesh bakedMesh = new Mesh + { + name = newMeshName, + indexFormat = meshData.indexFormat + }; + + int vertexCount = meshData.vertexCount; + if (vertexCount <= 0) + { + Debug.LogError($"Mesh '{sourceMesh.name}' 不包含任何顶点。"); + Object.DestroyImmediate(bakedMesh); + return null; + } + + using (NativeArray vertices = new NativeArray(vertexCount, Allocator.Temp)) + { + meshData.GetVertices(vertices); + bakedMesh.SetVertices(vertices); + } + + if (meshData.HasVertexAttribute(VertexAttribute.Normal)) + { + using (NativeArray normals = new NativeArray(vertexCount, Allocator.Temp)) + { + meshData.GetNormals(normals); + bakedMesh.SetNormals(normals); + } + } + + if (meshData.HasVertexAttribute(VertexAttribute.Tangent)) + { + using (NativeArray tangents = new NativeArray(vertexCount, Allocator.Temp)) + { + meshData.GetTangents(tangents); + bakedMesh.SetTangents(tangents); + } + } + + if (meshData.HasVertexAttribute(VertexAttribute.TexCoord0)) + { + using (NativeArray uv0 = new NativeArray(vertexCount, Allocator.Temp)) + { + meshData.GetUVs(0, uv0); + bakedMesh.SetUVs(0, uv0); + } + } + + int subMeshCount = sourceMesh.subMeshCount; + bakedMesh.subMeshCount = subMeshCount; + + bool hasTriangleSubMesh = false; + for (int subMeshIndex = 0; subMeshIndex < subMeshCount; subMeshIndex++) + { + SubMeshDescriptor subMesh = meshData.GetSubMesh(subMeshIndex); + if (subMesh.topology == MeshTopology.Triangles && subMesh.indexCount > 0) + { + hasTriangleSubMesh = true; + if (meshData.indexFormat == IndexFormat.UInt16) + { + using (NativeArray indices = new NativeArray((int)subMesh.indexCount, Allocator.Temp)) + { + meshData.GetIndices(indices, subMeshIndex, true); + bakedMesh.SetIndices(indices, MeshTopology.Triangles, subMeshIndex, false); + } + } + else + { + using (NativeArray indices = new NativeArray((int)subMesh.indexCount, Allocator.Temp)) + { + meshData.GetIndices(indices, subMeshIndex, true); + bakedMesh.SetIndices(indices, MeshTopology.Triangles, subMeshIndex, false); + } + } + } + else + { + bakedMesh.SetIndices(System.Array.Empty(), MeshTopology.Triangles, subMeshIndex, false); + } + } + + if (!hasTriangleSubMesh) + { + Debug.LogError($"Mesh '{sourceMesh.name}' 不包含可烘焙的三角形 SubMesh。"); + Object.DestroyImmediate(bakedMesh); + return null; + } + + bakedMesh.RecalculateBounds(); + return bakedMesh; + } + } + + private void SyncSlotsToMesh() + { + foreach (Object editorTarget in targets) + { + MeshUI meshUI = editorTarget as MeshUI; + if (meshUI == null) + { + continue; + } + + SerializedObject targetObject = new SerializedObject(meshUI); + SerializedProperty meshProp = targetObject.FindProperty("mesh"); + SerializedProperty materialsProp = targetObject.FindProperty("subMeshMaterials"); + Mesh mesh = meshProp.objectReferenceValue as Mesh; + int targetSize = mesh != null ? mesh.subMeshCount : 0; + materialsProp.arraySize = Mathf.Max(0, targetSize); + targetObject.ApplyModifiedProperties(); + + EditorUtility.SetDirty(meshUI); + PrefabUtility.RecordPrefabInstancePropertyModifications(meshUI); + } + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/MeshUIInspector.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/MeshUIInspector.cs.meta new file mode 100644 index 00000000..34ad1498 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/MeshUIInspector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 10b17bb5e66542688383e3f64f44717c +timeCreated: 1774473600 diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/NBCompatEditorUtility.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/NBCompatEditorUtility.cs new file mode 100644 index 00000000..2ab709d3 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/NBCompatEditorUtility.cs @@ -0,0 +1,31 @@ +using UnityEditor; +using UnityEngine.Rendering; + +namespace NBShaderEditor +{ + public static class ShaderGUIUnityCompat + { + public static ShaderPropertyType GetPropertyType(MaterialProperty property) + { +#if UNITY_6000_1_OR_NEWER + return property.propertyType; +#else +#pragma warning disable 0618 + return (ShaderPropertyType)property.type; +#pragma warning restore 0618 +#endif + } + + public static bool HasHdrFlag(MaterialProperty property) + { +#if UNITY_6000_1_OR_NEWER + return (property.propertyFlags & ShaderPropertyFlags.HDR) != 0; +#else +#pragma warning disable 0618 + return (((ShaderPropertyFlags)property.flags) & ShaderPropertyFlags.HDR) != 0; +#pragma warning restore 0618 +#endif + } + + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/NBCompatEditorUtility.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/NBCompatEditorUtility.cs.meta new file mode 100644 index 00000000..264b2694 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/NBCompatEditorUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ab0b838b256742c994e033e50aca5be0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings.meta new file mode 100644 index 00000000..68ef5e96 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f6342c05c0b5437abd5d7332652ef16b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings/NBFXProjectSettings.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings/NBFXProjectSettings.cs new file mode 100644 index 00000000..b9d4db10 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings/NBFXProjectSettings.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public enum NBFXLanguageMode + { + FollowEditor, + Chinese, + English + } + + [FilePath("ProjectSettings/NB_FXSettings.asset", FilePathAttribute.Location.ProjectFolder)] + public sealed class NBFXProjectSettings : ScriptableSingleton + { + public const string SettingsPath = "Project/NB_FX"; + + private const string LocalizationTableName = "NBShader"; + private const string LocalizationCsvAssetPath = "Packages/com.xuanxuan.nb.fx/NBShaders2/Editor/Localization/NBShaderInspectorLocalization.csv"; + private const string FoldoutSessionPrefix = "NBFXProjectSettings.Foldout."; + + private sealed class SettingsSection + { + public string id; + public Func titleProvider; + public Action guiHandler; + public List keywords; + public int order; + public GUIContent titleContent; + public string titleLanguage; + } + + private static readonly string[] LanguageOptionsChineseFallback = + { + "跟随编辑器", + "中文", + "英文" + }; + private static readonly string[] LanguageOptionsEnglishFallback = + { + "Follow Editor", + "Chinese", + "English" + }; + private static readonly List s_Sections = new List(); + private static readonly Dictionary s_ProjectSettingsContentCache = + new Dictionary(StringComparer.Ordinal); + private static GUIStyle s_FoldoutHeaderStyle; + private static string s_ProjectSettingsEditorLanguage; + private static string[] s_ProjectSettingsLanguageOptions; + + [SerializeField] + private NBFXLanguageMode languageMode = NBFXLanguageMode.FollowEditor; + + public static NBFXLanguageMode LanguageMode => instance.languageMode; + + public static void SetLanguageMode(NBFXLanguageMode mode) + { + if (instance.languageMode == mode) + { + return; + } + + instance.languageMode = mode; + instance.Save(true); + UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); + } + + public static void RegisterSettingsSection( + string id, + Func titleProvider, + Action guiHandler, + IEnumerable keywords = null, + int order = 0) + { + if (string.IsNullOrEmpty(id) || guiHandler == null) + { + return; + } + + var section = new SettingsSection + { + id = id, + titleProvider = titleProvider, + guiHandler = guiHandler, + keywords = keywords == null ? new List() : new List(keywords), + order = order + }; + + for (int i = 0; i < s_Sections.Count; i++) + { + if (!string.Equals(s_Sections[i].id, id, StringComparison.Ordinal)) + { + continue; + } + + s_Sections[i] = section; + SortSections(); + return; + } + + s_Sections.Add(section); + SortSections(); + } + + [SettingsProvider] + public static SettingsProvider CreateSettingsProvider() + { + var provider = new SettingsProvider(SettingsPath, SettingsScope.Project) + { + label = "NB_FX", + guiHandler = DrawSettingsGUI, + keywords = BuildKeywords() + }; + + return provider; + } + + private static void DrawSettingsGUI(string searchContext) + { + EnsureProjectSettingsContentCacheForEditorLanguage(); + + if (DrawSectionFoldout( + "General", + ProjectSettingsContent("projectSettings.generalSection", "基础设置", "General Settings"))) + { + EditorGUI.BeginChangeCheck(); + var selectedMode = (NBFXLanguageMode)EditorGUILayout.Popup( + ProjectSettingsContent("projectSettings.defaultLanguage", "默认语言", "Default Language"), + (int)LanguageMode, + ProjectSettingsLanguageOptions()); + + if (EditorGUI.EndChangeCheck()) + { + SetLanguageMode(selectedMode); + } + } + + DrawRegisteredSections(searchContext); + } + + private static void DrawRegisteredSections(string searchContext) + { + for (int i = 0; i < s_Sections.Count; i++) + { + SettingsSection section = s_Sections[i]; + EditorGUILayout.Space(10f); + if (DrawSectionFoldout(section.id, GetSectionTitleContent(section))) + { + section.guiHandler(searchContext); + } + } + } + + private static bool DrawSectionFoldout(string id, GUIContent content) + { + string sessionKey = FoldoutSessionPrefix + id; + bool expanded = SessionState.GetBool(sessionKey, true); + EditorGUI.BeginChangeCheck(); + bool nextExpanded = EditorGUILayout.Foldout(expanded, content, true, FoldoutHeaderStyle); + if (EditorGUI.EndChangeCheck()) + { + SessionState.SetBool(sessionKey, nextExpanded); + } + + return nextExpanded; + } + + private static GUIStyle FoldoutHeaderStyle + { + get + { + if (s_FoldoutHeaderStyle == null) + { + s_FoldoutHeaderStyle = new GUIStyle(EditorStyles.foldout) + { + fontStyle = FontStyle.Bold + }; + } + + return s_FoldoutHeaderStyle; + } + } + + private static GUIContent ProjectSettingsContent(string key, string chineseFallback, string englishFallback) + { + EnsureProjectSettingsContentCacheForEditorLanguage(); + + GUIContent content; + if (s_ProjectSettingsContentCache.TryGetValue(key, out content)) + return content; + + var text = ProjectSettingsText(key, chineseFallback, englishFallback, s_ProjectSettingsEditorLanguage); + content = new GUIContent(text, text); + s_ProjectSettingsContentCache.Add(key, content); + return content; + } + + private static string ProjectSettingsText( + string key, + string chineseFallback, + string englishFallback, + string editorLanguage) + { + string fallback = IsEnglishLanguage(editorLanguage) ? englishFallback : chineseFallback; + return ShaderGUILocalization.GetInspectorText(LocalizationTableName, key, fallback, editorLanguage); + } + + private static string[] ProjectSettingsLanguageOptions() + { + EnsureProjectSettingsContentCacheForEditorLanguage(); + if (s_ProjectSettingsLanguageOptions != null) + return s_ProjectSettingsLanguageOptions; + + string[] fallback = IsEnglishLanguage(s_ProjectSettingsEditorLanguage) + ? LanguageOptionsEnglishFallback + : LanguageOptionsChineseFallback; + s_ProjectSettingsLanguageOptions = ShaderGUILocalization.GetInspectorOptions( + LocalizationTableName, + "projectSettings.languageMode", + fallback, + s_ProjectSettingsEditorLanguage); + return s_ProjectSettingsLanguageOptions; + } + + private static GUIContent GetSectionTitleContent(SettingsSection section) + { + if (section.titleProvider != null) + { + string language = ShaderGUILocalization.GetCurrentLanguage(LocalizationTableName); + if (section.titleContent != null && + string.Equals(section.titleLanguage, language, StringComparison.Ordinal)) + { + return section.titleContent; + } + + section.titleLanguage = language; + section.titleContent = section.titleProvider(); + return section.titleContent; + } + + GUIContent content; + if (s_ProjectSettingsContentCache.TryGetValue(section.id, out content)) + return content; + + content = new GUIContent(section.id, section.id); + s_ProjectSettingsContentCache.Add(section.id, content); + return content; + } + + private static void EnsureProjectSettingsContentCacheForEditorLanguage() + { + RegisterLocalization(); + string editorLanguage = ShaderGUILocalization.GetEditorLanguageName(); + if (string.Equals(s_ProjectSettingsEditorLanguage, editorLanguage, StringComparison.Ordinal)) + return; + + s_ProjectSettingsEditorLanguage = editorLanguage; + s_ProjectSettingsContentCache.Clear(); + s_ProjectSettingsLanguageOptions = null; + } + + private static bool IsEnglishLanguage(string language) + { + return string.Equals(language, ShaderGUILocalization.EnglishLanguage, StringComparison.OrdinalIgnoreCase); + } + + private static void RegisterLocalization() + { + ShaderGUILocalization.RegisterCsv(LocalizationTableName, LocalizationCsvAssetPath); + } + + private static HashSet BuildKeywords() + { + var keywords = new HashSet + { + "NB_FX", + "Language", + "语言", + "默认语言", + "Default Language", + "General Settings", + "基础设置", + "NBShader" + }; + + for (int i = 0; i < s_Sections.Count; i++) + { + List sectionKeywords = s_Sections[i].keywords; + if (sectionKeywords == null) + { + continue; + } + + for (int keywordIndex = 0; keywordIndex < sectionKeywords.Count; keywordIndex++) + { + keywords.Add(sectionKeywords[keywordIndex]); + } + } + + return keywords; + } + + private static void SortSections() + { + s_Sections.Sort((a, b) => + { + int orderCompare = a.order.CompareTo(b.order); + if (orderCompare != 0) + { + return orderCompare; + } + + return string.CompareOrdinal(a.id, b.id); + }); + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings/NBFXProjectSettings.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings/NBFXProjectSettings.cs.meta new file mode 100644 index 00000000..396b35d2 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ProjectSettings/NBFXProjectSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f5f19e24bcae4dcc8e06c4550b9b1029 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIHelper.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIHelper.cs new file mode 100644 index 00000000..f723a9c0 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIHelper.cs @@ -0,0 +1,2036 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.AnimatedValues; +// using UnityEditor.Rendering.Universal.ShaderGUI; +using UnityEngine; +using UnityEditor; +using NBShader; + +namespace NBShaderEditor +{ + /* + 多选材质面板的原则记录: + 0、多选后 同时只会有1个matEditor。每个属性只会有一个MaterialProperty。但会有多个Mat以及Mat属性值。会有多个ShaderFlag以及ShaderFlag值。 + 1、当多选后,属性处于Mixed状态时。对propety.Value进行设置是不合法的。只有非Mixed状态才会完全设置。包括这样对property.Value值进行判断也是非法的。如果在不确定Mixed的情况下,应该通过遍历Mats[i].Get或Set进行操作。Flag亦同理。 + 2、drawBlock应该都传Property,让DrawBlock内能知道Mixed状态。然后在Block内需要判断状态是否明确才进行相关的操作。 + 3、drawBlock一般放需要绘制的行为。对数值修改的行为统一放到OnValueChangeCheckBlock。 + 4、所有在GUI上存储,并需要后续判断的状态,需要可以标记mixed状态。如果是枚举,需要有一个指定为-1的UnKnownOrMixed枚举。如果是bool,应该改为int值,并规定-1为UnKnownOrMixed状态。 + 5、对于属性值的更改设定,都应该在OnValueChange的情况下进行。 + 6、对于Toggle作用的方法,均应该有EditorOnly的Property进行标记Toggle储存。Keywords或者Flag应该是设定结果,而非Toggle标记。 + 7、DrawVectorComponent这种多个GUI公用一个property属性的情况,需要有手动的提供各个Component是否是Mixed的方案。 + */ + public class ShaderGUIHelper + { + public ShaderGUIHelper() + { + Undo.undoRedoPerformed += OnUndoRedoPerformed; + } + private void OnUndoRedoPerformed()//定义一个Undo回调 + { + if(!shader) return;//会有一些空的Helper对象 + DrawGradientUndoPerformed(); + ResetTool?.NeedUpdate(); + } + + public class ShaderPropertyPack + { + public MaterialProperty property; + public string name; + public int index; + } + + public List mats; + public MaterialEditor matEditor; + public Shader shader; + // public List ShaderPropertyPacks = new List(); + public Dictionary ShaderPropertyPacksDic = + new Dictionary(); + public ShaderFlagsBase[] shaderFlags = null; + + public bool isClearUnUsedTexture = false; + + Color defaultBackgroundColor; + Color animatedBackgroundColor=>Color.red; + + public void Init(MaterialEditor materialEditor, MaterialProperty[] properties, + ShaderFlagsBase[] shaderFlags_in = null, List mats_in = null) + { + defaultBackgroundColor = GUI.backgroundColor; + shaderFlags = shaderFlags_in; + // ShaderPropertyPacks.Clear(); + matEditor = materialEditor; + mats = mats_in; + if (mats[0].shader != shader) + { + shader = mats[0].shader; + ShaderPropertyPacksDic.Clear(); + for (int i = 0; i < shader.GetPropertyCount(); i++) + { + ShaderPropertyPack pack = new ShaderPropertyPack(); + pack.name = shader.GetPropertyName(i); + for (int index = 0; index < properties.Length; ++index) + { + if (properties[index] != null && properties[index].name == pack.name) + { + pack.property = properties[index]; + pack.index = index; + break; + } + else + { + if (index == properties.Length - 1) + { + Debug.LogError(pack.name + "找不到Properties"); + } + } + } + + // ShaderPropertyPacks.Add(pack); + ShaderPropertyPacksDic.Add(pack.name,pack); + } + } + else + { + for (int i = 0; i < shader.GetPropertyCount(); i++) + { + string propertyName = shader.GetPropertyName(i); + ShaderPropertyPacksDic[propertyName].property = properties[i]; + } + + } + + + if (ResetTool == null) + { + ResetTool = new ShaderGUIResetTool(this); + } + else + { + ResetTool.EndInit(); + ResetTool.Update(); + } + + isClearUnUsedTexture = false; + + } + + private ShaderGUIToolBar _toolBar; + + public ShaderGUIResetTool ResetTool; + public List renderersUsingThisMaterial = new List(); + + Dictionary<(string,string),string> propertyPathDic = new Dictionary<(string,string), string>(); + + public void InitRenderers(List rendererList) + { + renderersUsingThisMaterial = rendererList; + propertyPathDic.Clear(); + } + + public bool IsPropertyAnimated(string propertyName,params string[] componentNames) + { + if (AnimationMode.InAnimationMode()) + { + + // string propertyPath = "material." + propertyName; + + foreach (var r in renderersUsingThisMaterial) + { + if (componentNames.Length > 0) + { + foreach (var component in componentNames) + { + + string propertyPath; + if (propertyPathDic.ContainsKey((propertyName, component))) + { + propertyPath = propertyPathDic[(propertyName, component)]; + } + else + { + propertyPath = "material." + propertyName +"." +component; + propertyPathDic.Add((propertyName, component), propertyPath); + } + if (AnimationMode.IsPropertyAnimated(r, propertyPath)) + { + return true; + } + } + } + else + { + string propertyPath; + if (propertyPathDic.ContainsKey((propertyName,""))) + { + propertyPath = propertyPathDic[(propertyName, "")]; + } + else + { + propertyPath = "material." + propertyName; + propertyPathDic.Add((propertyName,""), propertyPath); + } + if (AnimationMode.IsPropertyAnimated(r, propertyPath)) + { + // Debug.Log(propertyName); + return true; + } + } + } + } + + return false; + } + + public void DrawToolBar() + { + if (_toolBar == null) _toolBar = new ShaderGUIToolBar(this); + _toolBar.DrawToolbar(); + } + + public void DrawToggleFoldOut(int foldOutFlagBit,int foldOutFlagIndex, int animBoolIndex,string label, string propertyName, + int flagBitsName = 0, + int flagIndex = 0, string shaderKeyword = null, string shaderPassName = null, bool isIndentBlock = true, FontStyle fontStyle = FontStyle.Normal, + Action drawBlock = null,Action drawEndChangeCheck = null,bool isSharedGlobalParent = false) + { + bool foldOutState = shaderFlags[0].CheckFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + AnimBool animBool = GetAnimBool(foldOutFlagBit, animBoolIndex, foldOutFlagIndex); //foldOut里的第一组。 + animBool.target = foldOutState; + DrawToggleFoldOut(ref animBool, label, propertyName, flagBitsName, flagIndex, shaderKeyword, + shaderPassName, isIndentBlock, fontStyle, drawBlock, drawEndChangeCheck,isSharedGlobalParent:isSharedGlobalParent); + foldOutState = animBool.target; + if (foldOutState) + { + shaderFlags[0].SetFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + } + else + { + shaderFlags[0].ClearFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + } + } + + public void ColorProperty(string label, string propertyName,bool showAlpha = true) + { + EditorGUILayout.BeginHorizontal(); + ShaderPropertyPack shaderPropertyPack = ShaderPropertyPacksDic[propertyName]; + MaterialProperty prop = shaderPropertyPack.property; + Color color = shaderPropertyPack.property.colorValue; + Rect position = EditorGUILayout.GetControlRect(); + // MaterialEditor.BeginProperty(position, prop); + + EditorGUI.BeginChangeCheck(); + bool hdr = ShaderGUIUnityCompat.HasHdrFlag(prop); + if (IsPropertyAnimated(propertyName,"r","g","b","a")) + { + GUI.backgroundColor = animatedBackgroundColor; + } + color = EditorGUI.ColorField(position, new GUIContent(label), prop.colorValue, true, showAlpha, hdr); + GUI.backgroundColor = defaultBackgroundColor; + Action onEndChaneChange = () => + { + prop.colorValue = color; + ResetTool.CheckOnValueChange((label,propertyName)); + }; + if (EditorGUI.EndChangeCheck()) + { + onEndChaneChange(); + } + ResetTool.DrawResetModifyButton(new Rect(),(label,shaderPropertyPack.name),shaderPropertyPack,resetAction: () => + { + color = prop.colorValue; + },onValueChangedCallBack: onEndChaneChange); + // MaterialEditor.EndProperty(); + // matEditor.ColorProperty(GetProperty(propertyName), label); + + EditorGUILayout.EndHorizontal(); + ResetTool.EndResetModifyButtonScope(); + } + + public void DrawBigBlockFoldOut(int foldOutFlagBit,int foldOutFlagIndex,int animBoolIndex ,string label, Action drawBlock,bool isResetButtonBias = true) + { + EditorGUILayout.Space(); + DrawFoldOut(foldOutFlagBit,foldOutFlagIndex,animBoolIndex, label,FontStyle.Bold, drawBlock,isResetButtonBias); + GuiLine(); + } + + private AnimBool[] animBoolArr = new AnimBool[96];//先假定有3组。和存好的bit一一对应。 + + public AnimBool GetAnimBool(int flagBit, int AnimBoolIndex,int flagIndex) + { + int bitPos = 0; + for (int i = 0; i < 32; i++) + { + if ((flagBit & (1 << i)) > 0) + { + bitPos = i; + break; + } + } + int arrIndex = AnimBoolIndex * 32 + bitPos; + // Debug.Log(arrIndex.ToString() +"---"+ animBoolArr[arrIndex]); + if (animBoolArr[arrIndex] == null) + { + animBoolArr[arrIndex] = new AnimBool(shaderFlags[0].CheckFlagBits(flagBit,index:flagIndex)); + } + + animBoolArr[arrIndex].speed = 10f; + + return animBoolArr[arrIndex]; + } + + public void DrawFoldOut(int foldOutFlagBit,int foldOutFlagIndex,int animBoolIndex, String label,FontStyle fontStyle = FontStyle.Normal, Action drawBlock = null,bool isResetButtonBias = true) + { + bool foldOutState = shaderFlags[0].CheckFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + AnimBool animBool = GetAnimBool(foldOutFlagBit, animBoolIndex, foldOutFlagIndex); + animBool.target = foldOutState; + + EditorGUILayout.BeginHorizontal(); + var rect = EditorGUILayout.GetControlRect(); + var foldoutRect = new Rect(rect.x, rect.y, rect.width, rect.height); + foldoutRect.width -= 2 * ResetTool.ResetButtonSize; + var labelRect = new Rect(rect.x + 2f, rect.y, rect.width - 2f, rect.height); + var resetRect = rect; + resetRect.x = rect.x + rect.width - ResetTool.ResetButtonSize ; + if (isResetButtonBias) resetRect.x -= 3f; + resetRect.width = ResetTool.ResetButtonSize; + + animBool.target = EditorGUI.Foldout(foldoutRect, animBool.target, string.Empty, true); + + FontStyle origFontStyle = EditorStyles.label.fontStyle; + EditorStyles.label.fontStyle = fontStyle; + EditorGUI.LabelField(labelRect, label); + EditorStyles.label.fontStyle = origFontStyle; + + ResetTool.DrawResetModifyButton(resetRect,label); + EditorGUILayout.EndHorizontal(); + + float faded = animBool.faded; + // if (faded == 0) faded = 0.00001f; + if (faded == 0 && ResetTool.IsInitResetData) faded = 0.00001f; + if (EditorGUILayout.BeginFadeGroup(faded)) + { + EditorGUI.indentLevel++; + drawBlock?.Invoke(); + EditorGUI.indentLevel--; + } + EditorGUILayout.EndFadeGroup(); + foldOutState = animBool.target; + if (foldOutState) + { + shaderFlags[0].SetFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + } + else + { + shaderFlags[0].ClearFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + } + ResetTool.EndResetModifyButtonScope(); + } + + public void DrawBigBlockWithToggle(String label, string propertyName, int flagBitsName = 0, int flagIndex = 0, + string shaderKeyword = null, string shaderPassName = null, string shaderPassName2 = null, + Action drawBlock = null) + { + + DrawToggle(label, propertyName, flagBitsName, flagIndex, shaderKeyword, shaderPassName, shaderPassName2, + isIndentBlock: true, FontStyle.Bold, drawBlock: drawBlock); + GuiLine(); + + } + + public void DrawToggleFoldOut(ref AnimBool foldOutAnimBool, String label, string propertyName, + int flagBitsName = 0, + int flagIndex = 0, string shaderKeyword = null, string shaderPassName = null, bool isIndentBlock = true, + FontStyle fontStyle = FontStyle.Normal, + Action drawBlock = null, Action drawEndChangeCheck = null,bool isSharedGlobalParent = false) + { + ShaderPropertyPack propertyPack = ShaderPropertyPacksDic[propertyName]; + MaterialProperty toggleProp = GetProperty(propertyName); + + if (fontStyle == FontStyle.Bold) + { + EditorGUILayout.Space(); + } + + EditorGUILayout.BeginHorizontal(); + var rect = EditorGUILayout.GetControlRect(); + var toggleRect = rect; + toggleRect.x += EditorGUIUtility.labelWidth; + toggleRect.width -= EditorGUIUtility.labelWidth; + + var foldoutRect = new Rect(rect.x, rect.y, rect.width, rect.height); + foldoutRect.width = toggleRect.x - foldoutRect.x; + var labelRect = new Rect(rect.x , rect.y, rect.width , rect.height); + + // bool isToggle = false; + // 必须先画Toggle,不然按钮会被FoldOut和Label覆盖。 + DrawToggle(string.Empty, propertyName, flagBitsName, flagIndex, shaderKeyword, shaderPassName, isIndentBlock: false, fontStyle: FontStyle.Normal, rect: toggleRect, drawEndChangeCheck: drawEndChangeCheck,isSharedGlobalParent:isSharedGlobalParent); + + foldOutAnimBool.target = EditorGUI.Foldout(foldoutRect, foldOutAnimBool.target, string.Empty, true); + var origFontStyle = EditorStyles.label.fontStyle; + EditorStyles.label.fontStyle = fontStyle; + + EditorGUI.LabelField(labelRect, label); + EditorStyles.label.fontStyle = origFontStyle; + EditorGUILayout.EndHorizontal(); + if (isIndentBlock) EditorGUI.indentLevel++; + float faded = foldOutAnimBool.faded; + if (faded == 0 && ResetTool.IsInitResetData) faded = 0.0001f; //用于欺骗FadeGroup,不要让他真的关闭了。这样会藏不住相关的GUI。我们的目的是,GUI藏住,但是逻辑还是在跑。drawBlock要执行。 + if (EditorGUILayout.BeginFadeGroup(faded)) + { + bool isDisabledGroup = toggleProp.hasMixedValue || toggleProp.floatValue < 0.5f; + EditorGUI.BeginDisabledGroup(isDisabledGroup); + + drawBlock?.Invoke(toggleProp); + EditorGUI.EndDisabledGroup(); + } + EditorGUILayout.EndFadeGroup(); + if (isIndentBlock) EditorGUI.indentLevel--; + + ResetTool.EndResetModifyButtonScope();//开始是在DrawToggle里开始的 + + } + + public void DrawToggle(String label, string propertyName, int flagBitsName = 0, int flagIndex = 0, + string shaderKeyword = null, string shaderPassName = null, string shaderPassName2 = null, + bool isIndentBlock = true, FontStyle fontStyle = FontStyle.Normal, Rect rect = new Rect(), + Action drawBlock = null, Action drawEndChangeCheck = null,bool isSharedGlobalParent = false) + { + if (GetProperty(propertyName) == null) + return; + + if (fontStyle == FontStyle.Bold) + { + EditorGUILayout.Space(); + } + + MaterialProperty toggleProperty = GetProperty(propertyName); + ShaderPropertyPack propertyPack = ShaderPropertyPacksDic[propertyName]; + EditorGUI.showMixedValue = toggleProperty.hasMixedValue; + + EditorGUI.BeginChangeCheck(); + bool isToggle = toggleProperty.floatValue > 0.5f ? true : false; + var origFontStyle = EditorStyles.label.fontStyle; + EditorStyles.label.fontStyle = fontStyle; + Rect resetButtonRect = rect; + if (label.Length <= 0) //给FoldOut功能使用。 + { + rect.x += 2f; + rect.width -= 24f;//避免覆盖ResetButton + isToggle = EditorGUI.Toggle(rect, isToggle, EditorStyles.toggle); + resetButtonRect.x = resetButtonRect.x + resetButtonRect.width - ResetTool.ResetButtonSize; + resetButtonRect.width = ResetTool.ResetButtonSize; + } + else + { + Rect newRect = EditorGUILayout.GetControlRect(); + Rect newToggleRect = newRect; + Rect newLabelRect = newRect; + // newLabelRect.x += indent; + newLabelRect.width = EditorGUIUtility.labelWidth; + newToggleRect.x += EditorGUIUtility.labelWidth +2f; + newToggleRect.width -= EditorGUIUtility.labelWidth +2f; + resetButtonRect = newToggleRect; + resetButtonRect.x = resetButtonRect.x + resetButtonRect.width - ResetTool.ResetButtonSize; + resetButtonRect.width = ResetTool.ResetButtonSize; + EditorGUI.LabelField(newLabelRect, label); + isToggle = EditorGUI.Toggle(newToggleRect, isToggle, EditorStyles.toggle); + } + + EditorStyles.label.fontStyle = origFontStyle; + Action onEndChangeCheck = () => + { + toggleProperty.floatValue = isToggle ? 1.0f : 0.0f; + ResetTool.CheckOnValueChange((label,propertyName)); + if (!toggleProperty.hasMixedValue) + { + for (int i = 0; i < mats.Count; i++) + { + if (isToggle) + { + mats[i].SetFloat(propertyName,1); + + if (flagBitsName != 0 && shaderFlags[i] != null) + { + shaderFlags[i].SetFlagBits(flagBitsName, index: flagIndex); + } + + if (shaderKeyword != null) + { + mats[i].EnableKeyword(shaderKeyword); + } + + if (shaderPassName != null) + { + mats[i].SetShaderPassEnabled(shaderPassName, true); + } + + if (shaderPassName2 != null) + { + mats[i].SetShaderPassEnabled(shaderPassName2, true); + } + } + else + { + + mats[i].SetFloat(propertyName,0); + + + if (flagBitsName != 0 && shaderFlags[i] != null) + { + shaderFlags[i].ClearFlagBits(flagBitsName, index: flagIndex); + } + + if (shaderKeyword != null) + { + mats[i].DisableKeyword(shaderKeyword); + } + + if (shaderPassName != null) + { + mats[i].SetShaderPassEnabled(shaderPassName, false); + } + + if (shaderPassName2 != null) + { + mats[i].SetShaderPassEnabled(shaderPassName2, false); + } + } + } + } + drawEndChangeCheck?.Invoke(toggleProperty); + }; + if (EditorGUI.EndChangeCheck()) + { + onEndChangeCheck(); + } + + + ResetTool.DrawResetModifyButton(resetButtonRect,(label,propertyPack.name),propertyPack,resetAction: () => + { + isToggle = propertyPack.property.floatValue > 0.5f ? true : false; + },onValueChangedCallBack:onEndChangeCheck,isSharedGlobalParent:isSharedGlobalParent); + + + if (isIndentBlock) EditorGUI.indentLevel++; + drawBlock?.Invoke(toggleProperty); + if (isIndentBlock) EditorGUI.indentLevel--; + + EditorGUI.showMixedValue = false; + if (rect.width <= 0) + { + ResetTool.EndResetModifyButtonScope();//如果是DrawFoldOut,需要在DrawFoldOut里去结束。 + } + + if (ResetTool.IsInitResetData) + { + ResetTool.CheckOnValueChange((label,propertyPack.name));//为什么是在这里验证而不是再ResetTool里。 + } + } + + void RangeVecHasMixedValue(string rangePropertyName, out bool minValueHasMixed, out bool maxValueHasMixed) + { + minValueHasMixed = false; + maxValueHasMixed = false; + if (mats.Count > 1) + { + MaterialProperty rangeProperty = GetProperty(rangePropertyName); + float minValue = 0; + float maxValue = 0; + for (int i = 0; i < mats.Count; i++) + { + Vector4 rangeVec = mats[i].GetVector(rangePropertyName); + if (i == 0) + { + minValue = rangeVec.x; + maxValue = rangeVec.y; + } + else + { + if (!Mathf.Approximately(minValue, rangeVec.x)) + { + minValueHasMixed = true; + } + + if (!Mathf.Approximately(maxValue, rangeVec.y)) + { + maxValueHasMixed = true; + } + } + } + } + } + + bool RangePropIsDefaultValue(string rangePropertyName) + { + MaterialProperty rangeProperty = GetProperty(rangePropertyName); + return mats[0].GetVector(rangePropertyName) == shader.GetPropertyDefaultVectorValue(ShaderPropertyPacksDic[rangePropertyName].index) && !rangeProperty.hasMixedValue; + } + + void DrawSlider(string label, ref float value,ref float min,ref float max,bool isValueMixed,string rangePropertyName = null,bool propIsAnimated = false) + { + if (rangePropertyName == null) + { + EditorGUI.showMixedValue = isValueMixed; + if (propIsAnimated) GUI.backgroundColor = animatedBackgroundColor; + value = EditorGUILayout.Slider(label,value,min,max); + GUI.backgroundColor = defaultBackgroundColor; + EditorGUI.showMixedValue = false; + } + else + { + Rect rect = EditorGUILayout.GetControlRect(); + Rect labelRect = rect; + labelRect.width = EditorGUIUtility.labelWidth; + Rect valueRect = rect; + valueRect.x += EditorGUIUtility.labelWidth; + valueRect.width -= EditorGUIUtility.labelWidth; + // EditorGUI.DrawRect(valueRect,Color.red); + float rangeWidth = 50f; + Rect minRect = valueRect; + minRect.width = rangeWidth; + minRect.x -= indent; + minRect.width += indent; + // EditorGUI.DrawRect(minRect,Color.green); + Rect maxRect = valueRect; + maxRect.x += valueRect.width; + maxRect.x -= rangeWidth; + maxRect.width = rangeWidth; + maxRect.x -= indent; + maxRect.width += indent; + valueRect.x += rangeWidth; + valueRect.width -= 2*rangeWidth; + valueRect.x -= indent; + valueRect.width += indent; + valueRect.x += 4f; + valueRect.width -= 8f; + EditorGUI.LabelField(labelRect, label); + + RangeVecHasMixedValue(rangePropertyName,out bool minValueHasMixed,out bool maxValueHasMixed); + + EditorGUI.showMixedValue = minValueHasMixed; + min = EditorGUI.FloatField(minRect, GUIContent.none, min); + EditorGUI.showMixedValue = maxValueHasMixed; + max = EditorGUI.FloatField(maxRect, GUIContent.none, max); + EditorGUI.showMixedValue = isValueMixed; + if (propIsAnimated) + { + GUI.backgroundColor = animatedBackgroundColor; + } + value = EditorGUI.Slider(valueRect, value, min, max); + GUI.backgroundColor = defaultBackgroundColor; + EditorGUI.showMixedValue = false; + } + } + + public void DrawSlider(string label, string propertyName,float min = 0,float max = 1,string rangePropertyName = null, Action drawBlock = null) + { + bool hasMixedValue = GetProperty(propertyName).hasMixedValue; + float f = GetProperty(propertyName).floatValue; + bool customedRange = rangePropertyName != null; + Vector4 rangeVec = Vector4.zero; + if (customedRange) + { + rangeVec = GetProperty(rangePropertyName).vectorValue; + } + EditorGUILayout.BeginHorizontal(); + EditorGUI.BeginChangeCheck(); + if (IsPropertyAnimated(propertyName)) + { + GUI.backgroundColor = animatedBackgroundColor; + } + + bool isPropAnimated = IsPropertyAnimated(propertyName); + if (customedRange) + { + DrawSlider(label, ref f, ref rangeVec.x,ref rangeVec.y,hasMixedValue,rangePropertyName,isPropAnimated); + } + else + { + DrawSlider(label, ref f, ref min,ref max,hasMixedValue,propIsAnimated:isPropAnimated); + } + + GUI.backgroundColor = defaultBackgroundColor; + Action endChangCallBack= () => + { + GetProperty(propertyName).floatValue = f; + if (customedRange) + { + GetProperty(rangePropertyName).vectorValue = rangeVec; + } + ResetTool.CheckOnValueChange((label,propertyName)); + }; + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + endChangCallBack.Invoke(); + } + ResetTool.DrawResetModifyButton(new Rect(),(label,propertyName),resetCallBack: () => + { + f = shader.GetPropertyDefaultFloatValue(ShaderPropertyPacksDic[propertyName].index); + if (customedRange) + { + rangeVec = shader.GetPropertyDefaultVectorValue(ShaderPropertyPacksDic[rangePropertyName].index); + } + },onValueChangedCallBack: () => + { + endChangCallBack(); + } + ,checkHasModifyOnValueChange: + () => + { + bool isModify = !Mathf.Approximately(mats[0].GetFloat(propertyName),shader.GetPropertyDefaultFloatValue(ShaderPropertyPacksDic[propertyName].index)); + if (customedRange) + { + isModify |= !RangePropIsDefaultValue(rangePropertyName); + } + return isModify; + },checkHasMixedValueOnValueChange: + () => + { + bool hasMixedValue = false; + hasMixedValue |= GetProperty(propertyName).hasMixedValue; + if (customedRange) + { + RangeVecHasMixedValue(rangePropertyName,out bool minValueHasMixed,out bool maxValueHasMixed); + hasMixedValue |= minValueHasMixed; + hasMixedValue |= maxValueHasMixed; + } + return hasMixedValue; + }); + EditorGUILayout.EndHorizontal(); + drawBlock?.Invoke(f); + ResetTool.EndResetModifyButtonScope(); + } + + + public void DrawFloat(string label, string propertyName, bool isReciprocal = false, + Action drawBlock = null) + { + EditorGUI.showMixedValue = GetProperty(propertyName).hasMixedValue; + MaterialProperty floatProperty = GetProperty(propertyName); + float f = floatProperty.floatValue; + if (isReciprocal) f = 1 / f; + EditorGUI.BeginChangeCheck(); + Action endChangeCallback = () => + { + floatProperty.floatValue = f; + ResetTool.CheckOnValueChange((label,propertyName)); + }; + + EditorGUILayout.BeginHorizontal(); + if (IsPropertyAnimated(propertyName)) + { + GUI.backgroundColor = animatedBackgroundColor; + } + f = EditorGUILayout.FloatField(label, f); + GUI.backgroundColor = defaultBackgroundColor; + + if (isReciprocal) f = 1 / f; + if (EditorGUI.EndChangeCheck()) + { + endChangeCallback.Invoke(); + } + + ResetTool.DrawResetModifyButton(new Rect(),(label,propertyName),ShaderPropertyPacksDic[propertyName],resetAction: () => + { + f = floatProperty.floatValue; + },onValueChangedCallBack:endChangeCallback); + EditorGUILayout.EndHorizontal(); + + drawBlock?.Invoke(floatProperty); + EditorGUI.showMixedValue = false; + ResetTool.EndResetModifyButtonScope(); + } + + Vector2 GetVec2InVec4(Vector4 vec4,bool isFirstLine) + { + if (isFirstLine) + { + return new Vector2(vec4.x, vec4.y); + } + else + { + return new Vector2(vec4.z, vec4.w); + } + } + + Vector4 SetVec2InVec4(Vector4 vec4,bool isFirstLine,Vector2 vec2Value) + { + if (isFirstLine) + { + vec4.x = vec2Value.x; + vec4.y = vec2Value.y; + return vec4; + } + else + { + vec4.z = vec2Value.x; + vec4.w = vec2Value.y; + return vec4; + } + } + + Vector2 GetVecInTwoLineDefaultValue(string propertyName, bool isFirstLine) + { + ShaderPropertyPack propertyPack = ShaderPropertyPacksDic[propertyName]; + Vector4 defaultVector = shader.GetPropertyDefaultVectorValue(propertyPack.index); + if (isFirstLine) + { + return new Vector2(defaultVector.x, defaultVector.y); + } + else + { + return new Vector2(defaultVector.z, defaultVector.w); + } + } + + bool Vector4In2LineHasMixedValue(string propertyName, bool isFirstLine) + { + MaterialProperty matProp = GetProperty(propertyName); + if (matProp.hasMixedValue) + { + Vector2 val = Vector2.zero; + for (int i = 0; i < mats.Count; i++) + { + Vector2 matValue = GetVec2InVec4(mats[i].GetVector(propertyName), isFirstLine); + if (i == 0) + { + val = matValue; + } + else + { + if (!val.Equals(matValue) ) + { + return true; + } + } + } + } + + return false; + } + + public void DrawVector4In2Line(string propertyName, string label , bool isFirstLine, + Action drawBlock = null) + { + EditorGUI.showMixedValue = Vector4In2LineHasMixedValue(propertyName, isFirstLine); + MaterialProperty property = GetProperty(propertyName); + (string,string) nameTuple = (label,propertyName); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + + Vector2 vec2 = GetVec2InVec4(property.vectorValue, isFirstLine); + // vec2 = EditorGUILayout.Vector2Field(label, vec2); + Rect rect = EditorGUILayout.GetControlRect(true); + Rect labelRect = rect; + labelRect.width = EditorGUIUtility.labelWidth - indent; + EditorGUI.LabelField(labelRect, label); + Rect vec2Rect = rect; + vec2Rect.x += labelRect.width; + vec2Rect.width -= labelRect.width; + if (isFirstLine) + { + if (IsPropertyAnimated(propertyName, "x", "y")) + { + GUI.backgroundColor = animatedBackgroundColor; + } + } + else + { + if (IsPropertyAnimated(propertyName, "z", "w")) + { + GUI.backgroundColor = animatedBackgroundColor; + } + } + vec2 = EditorGUI.Vector2Field(vec2Rect,"", vec2); + GUI.backgroundColor = defaultBackgroundColor; + + Action vec2OnEndChangeCheck = () => + { + int shaderID = Shader.PropertyToID(propertyName); + for (int i = 0; i < mats.Count; i++) + { + Vector4 vec4 = mats[i].GetVector(shaderID); + vec4 = SetVec2InVec4(vec4, isFirstLine, vec2); + if (mats.Count == 1) + { + GetProperty(propertyName).vectorValue = vec4; //为了K动画,多选不能K动画。 + } + else + { + mats[i].SetVector(shaderID, vec4); + } + } + ResetTool.CheckOnValueChange(nameTuple); + }; + + + if (EditorGUI.EndChangeCheck()) + { + vec2OnEndChangeCheck(); + } + EditorGUI.showMixedValue = false; + + ResetTool.DrawResetModifyButton(new Rect(),nameTuple, + resetCallBack:()=> + { + vec2 = GetVecInTwoLineDefaultValue(propertyName, isFirstLine); + vec2OnEndChangeCheck(); + }, + onValueChangedCallBack:vec2OnEndChangeCheck, + checkHasModifyOnValueChange: () => GetVec2InVec4(mats[0].GetVector(propertyName), isFirstLine) != GetVecInTwoLineDefaultValue(propertyName, isFirstLine), + checkHasMixedValueOnValueChange:()=>Vector4In2LineHasMixedValue(propertyName, isFirstLine)); + + drawBlock?.Invoke(); + ResetTool.EndResetModifyButtonScope(); + EditorGUILayout.EndHorizontal(); + + } + + float GetCompInVec4(Vector4 vec, string comp) + { + float f = 0; + switch (comp) + { + case "x": + f = vec.x; + break; + case "y": + f = vec.y; + break; + case "z": + f = vec.z; + break; + case "w": + f = vec.w; + break; + } + + return f; + } + + float GetCompDefaultValueInVec4(string propertyName, string comp) + { + ShaderPropertyPack propertyPack = ShaderPropertyPacksDic[propertyName]; + Vector4 defaultValue = shader.GetPropertyDefaultVectorValue(propertyPack.index); + return GetCompInVec4(defaultValue, comp); + } + + Vector4 SetCompInVec4(Vector4 vec, string comp, float value) + { + switch (comp) + { + case "x": + vec.x = value; + break; + case "y": + vec.y = value; + break; + case "z": + vec.z = value; + break; + case "w": + vec.w = value; + break; + } + + return vec; + } + + bool Vector4ComponentHasMixedValue(string propertyName, string channel) + { + MaterialProperty property = GetProperty(propertyName); + if (property.hasMixedValue) + { + float val = 0; + for (int i = 0; i < mats.Count; i++) + { + if (i == 0) + { + val = GetCompInVec4(mats[i].GetVector(propertyName),channel) ; + } + else + { + if (!val.Equals(GetCompInVec4(mats[i].GetVector(propertyName),channel)) ) + { + return true; + } + } + } + } + + return false; + + } + public void DrawVector4Component(string label, string propertyName, string channel, bool isSlider,float minValue = 0,float maxValue = 1, + string rangeVecPropName = null, float powerSlider = 1, float multiplier = 1, + bool isReciprocal = false, Action drawBlock = null, Action drawEndChangeCheckBlock = null) + { + bool hasMixedValue = Vector4ComponentHasMixedValue(propertyName, channel); + (string, string) nameTuple = (label, propertyName); + Vector4 vec = GetProperty(propertyName).vectorValue; + float f = GetCompInVec4(vec, channel); + Vector4 rangeVec = Vector4.zero; + bool isCustomedRange = rangeVecPropName != null; + if (isCustomedRange) + { + rangeVec = GetProperty(rangeVecPropName).vectorValue; + } + f *= multiplier; + if (isReciprocal) f = 1 / f; + EditorGUILayout.BeginHorizontal(); + EditorGUI.BeginChangeCheck(); + bool propIsAnimated = IsPropertyAnimated(propertyName, channel); + if (isSlider) + { + if (powerSlider > 1) + { + if (propIsAnimated) GUI.backgroundColor = animatedBackgroundColor; + f = PowerSlider(EditorGUILayout.GetControlRect(new GUILayoutOption[] { GUILayout.Height(18) }), + new GUIContent(label), f, minValue, maxValue, powerSlider); + GUI.backgroundColor = defaultBackgroundColor; + } + else + { + if (isCustomedRange) + { + DrawSlider(label,ref f,ref rangeVec.x,ref rangeVec.y,hasMixedValue,rangeVecPropName,propIsAnimated); + } + else + { + DrawSlider(label,ref f,ref minValue,ref maxValue,hasMixedValue,propIsAnimated:propIsAnimated); + } + } + } + else + { + EditorGUI.showMixedValue = hasMixedValue; + if(propIsAnimated) GUI.backgroundColor = animatedBackgroundColor; + f = EditorGUILayout.FloatField(label, f); + GUI.backgroundColor = defaultBackgroundColor; + EditorGUI.showMixedValue = false; + } + + if (isReciprocal) f = 1 / f; + f /= multiplier; + + Action floatVecEndChangeCheck = () => + { + int id= Shader.PropertyToID(propertyName); + for (int i = 0; i < mats.Count; i++) + { + Vector4 val = mats[i].GetVector(id); + val = SetCompInVec4(val, channel, f); + if (mats.Count == 1) + { + GetProperty(propertyName).vectorValue = val;//为了K动画,多选不能K动画。 + } + else + { + mats[i].SetVector(id, val); + } + if (isCustomedRange) + { + mats[i].SetVector(rangeVecPropName, rangeVec); + } + } + + drawEndChangeCheckBlock?.Invoke(f, hasMixedValue); + ResetTool.CheckOnValueChange(nameTuple); + }; + + if (EditorGUI.EndChangeCheck()) + { + floatVecEndChangeCheck(); + } + + ResetTool.DrawResetModifyButton(new Rect(),nameTuple, + resetCallBack:()=> + { + f = GetCompDefaultValueInVec4(propertyName, channel); + if (isCustomedRange) + { + rangeVec = shader.GetPropertyDefaultVectorValue(ShaderPropertyPacksDic[rangeVecPropName].index); + } + floatVecEndChangeCheck(); + },onValueChangedCallBack:floatVecEndChangeCheck, + checkHasModifyOnValueChange: () => + { + bool isEqual = Mathf.Approximately(GetCompInVec4(mats[0].GetVector(propertyName), channel), GetCompDefaultValueInVec4(propertyName, channel)); + if (isCustomedRange) + { + isEqual &= RangePropIsDefaultValue(rangeVecPropName); + } + return !isEqual; + }, + checkHasMixedValueOnValueChange: () => + { + bool hasMixedValue = Vector4ComponentHasMixedValue(propertyName, channel); + if (isCustomedRange) + { + RangeVecHasMixedValue(rangeVecPropName, out bool minValueHasMixed, out bool maxValueHasMixed); + hasMixedValue |= minValueHasMixed; + hasMixedValue |= maxValueHasMixed; + } + + return hasMixedValue; + }); + EditorGUILayout.EndHorizontal(); + + drawBlock?.Invoke(f,hasMixedValue); + ResetTool.EndResetModifyButtonScope(); + EditorGUI.showMixedValue = false; + } + + public void DrawVector4XYZComponet(string label, string propertyName, Action drawBlock = null) + { + EditorGUI.showMixedValue = GetProperty(propertyName).hasMixedValue; + (string, string) nameTuple = (label, propertyName); + Vector4 originVec = GetProperty(propertyName).vectorValue; + Vector3 vec = originVec; + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + vec = EditorGUILayout.Vector3Field(label, vec); + EditorGUI.showMixedValue = false; + Action drawEndChangeCheck = () => + { + GetProperty(propertyName).vectorValue = new Vector4(vec.x, vec.y, vec.z, originVec.w); + ResetTool.CheckOnValueChange(nameTuple); + + }; + if (EditorGUI.EndChangeCheck()) + { + drawEndChangeCheck(); + } + + ResetTool.DrawResetModifyButton(new Rect(),nameTuple,ShaderPropertyPacksDic[propertyName],resetAction: () => + { + vec = GetProperty(propertyName).vectorValue; + },onValueChangedCallBack:drawEndChangeCheck,vectorValeType:VectorValeType.XYZ); + EditorGUILayout.EndHorizontal(); + drawBlock?.Invoke(vec); + ResetTool.EndResetModifyButtonScope(); + } + + public enum SamplerWarpMode + { + Repeat, + Clamp, + RepeatX_ClampY, + ClampX_RepeatY + } + + public Rect GetRectAfterLabelWidth(Rect rect, bool ignoreIndent = false) + { + Rect rectAfterLabelWidth = MaterialEditor.GetRectAfterLabelWidth(rect); //右边缘是准的。 + Rect leftAlignedFieldRect = MaterialEditor.GetLeftAlignedFieldRect(rect); //左边缘是准的,实际有2f空隙。 + float x = leftAlignedFieldRect.x + 2f; + float width = rectAfterLabelWidth.x + rectAfterLabelWidth.width - x; + + var newRec = new Rect(x, rectAfterLabelWidth.y, width, rectAfterLabelWidth.height); + + if (ignoreIndent) + { + float indent = (float)EditorGUI.indentLevel * 15f; + newRec.x -= indent; + newRec.width += indent; + } + return newRec; + } + public void DrawTextureFoldOut(int foldOutFlagBit,int foldOutFlagIndex,int animBoolIndex,string label, string texturePropertyName, + string colorPropertyName = null, bool drawScaleOffset = true, bool drawWrapMode = false, + int flagBitsName = 0, int flagIndex = 2, Action drawBlock = null) + { + + bool foldOutState = shaderFlags[0].CheckFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + AnimBool animBool = GetAnimBool(foldOutFlagBit, animBoolIndex, foldOutFlagIndex); + animBool.target = foldOutState; + DrawTextureFoldOut(ref animBool, label, texturePropertyName, colorPropertyName, drawScaleOffset, + drawWrapMode, flagBitsName, flagIndex, drawBlock); + foldOutState = animBool.target; + if (foldOutState) + { + shaderFlags[0].SetFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + } + else + { + shaderFlags[0].ClearFlagBits(foldOutFlagBit, index: foldOutFlagIndex); + } + + } + + + public void DrawTextureFoldOut(ref AnimBool foldOutAnimBool, string label, string texturePropertyName, + string colorPropertyName = null, bool drawScaleOffset = true, bool drawWrapMode = false, + int wrapModeFlagBitsName = 0, int flagIndex = 2, Action drawBlock = null) + { + // EditorGUILayout.BeginHorizontal(); + // var rect = EditorGUILayout.GetControlRect(false,68f);//MaterialEditor.GetTextureFieldHeight() => 64f; + // var foldoutRect = new Rect(rect.x, rect.y, rect.width , rect.height); + // var textureThumbnialRect = new Rect(rect.x , rect.y, rect.width, rect.height); + // Texture texture = matEditor.TextureProperty(textureThumbnialRect,GetProperty(texturePropertyName), label, drawScaleOffset); + Texture texture = TextureProperty(GetProperty(texturePropertyName), label, drawScaleOffset); + // EditorGUILayout.EndHorizontal(); + + if (colorPropertyName != null) + { + // Rect colorPropRect = GetRectAfterLabelWidth(rect, true); + // colorPropRect.x -= EditorGUI.indentLevel + // EditorGUI.indentLevel++; + // Rect colorPropRect = EditorGUILayout.GetControlRect(false); + // Color color = matEditor.ColorProperty(colorPropRect, GetProperty(colorPropertyName), ""); + ColorProperty("",colorPropertyName,true); + // EditorGUI.indentLevel--; + } + var foldoutRect = EditorGUILayout.GetControlRect(false);//MaterialEditor.GetTextureFieldHeight() => 64f; + Rect labelRect = foldoutRect; + labelRect.width = EditorGUIUtility.labelWidth; + EditorGUI.LabelField(labelRect, label+"相关功能", EditorStyles.boldLabel); + foldOutAnimBool.target = EditorGUI.Foldout(foldoutRect, foldOutAnimBool.target, "", true); + float faded = foldOutAnimBool.faded; + if (faded == 0 && ResetTool.IsInitResetData) faded = 0.00001f; + + if(EditorGUILayout.BeginFadeGroup(faded)) + { + EditorGUI.BeginDisabledGroup(texture == null); + DrawAfterTexture(true, label, texturePropertyName, drawWrapMode, wrapModeFlagBitsName, flagIndex, drawBlock); + EditorGUI.EndDisabledGroup(); + } + EditorGUILayout.EndFadeGroup(); + } + + public void DrawTexture(string label, string texturePropertyName, string colorPropertyName = null, + bool drawScaleOffset = true, bool drawWrapMode = false, int wrapModeFlagBitsName = 0, int flagIndex = 2, + Action drawBlock = null) + { + bool hasTexture = mats[0].GetTexture(texturePropertyName) != null; + Texture texture = TextureProperty(GetProperty(texturePropertyName), label, drawScaleOffset); + if (colorPropertyName != null) + { + ColorProperty("",colorPropertyName,true); + } + + DrawAfterTexture(hasTexture, label, texturePropertyName, drawWrapMode, wrapModeFlagBitsName, + flagIndex, drawBlock); + } + + Texture TextureProperty(MaterialProperty textureProperty, string label, bool drawScaleOffset) + { + ShaderPropertyPack texturePropertyPack = ShaderPropertyPacksDic[textureProperty.name]; + if (!GUI.enabled && isClearUnUsedTexture&&textureProperty.textureValue) + { + Debug.Log("清除掉贴图:"+textureProperty.name,textureProperty.textureValue); + texturePropertyPack.property.textureValue = null; + } + float indentWidth = 15f; + float currentIndentWidth = EditorGUI.indentLevel * indentWidth; + float singleLineHeight = EditorGUIUtility.singleLineHeight; + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.GetControlRect(GUILayout.Width(EditorGUI.indentLevel * indentWidth)); + float textureFieldHeight = 3*singleLineHeight; + var textureRect = EditorGUILayout.GetControlRect(GUILayout.Height(textureFieldHeight),GUILayout.Width(textureFieldHeight)); + + EditorGUILayout.BeginVertical(); + var textureLabelRect = EditorGUILayout.GetControlRect(); + textureLabelRect.x -= currentIndentWidth; + textureLabelRect.width += currentIndentWidth; + EditorGUI.LabelField(textureLabelRect,label,EditorStyles.boldLabel); + + var textureResetButtonRect = textureLabelRect; + textureResetButtonRect.x += textureResetButtonRect.width; + textureResetButtonRect.x -= ResetTool.ResetButtonSize; + textureResetButtonRect.width = ResetTool.ResetButtonSize; + + float tillingOffsetLabelWidth = 30f; + Rect tillingRect = EditorGUILayout.GetControlRect(); + Rect tillingVec2Rect = tillingRect; + tillingVec2Rect.x += tillingOffsetLabelWidth; + tillingVec2Rect.width -= tillingOffsetLabelWidth; + tillingVec2Rect.width -= ResetTool.ResetButtonSize; + tillingVec2Rect.width -= 2f; + Rect tillingResetButtonRect = tillingRect; + tillingResetButtonRect.x = tillingResetButtonRect.x + tillingResetButtonRect.width - ResetTool.ResetButtonSize; + tillingResetButtonRect.width = ResetTool.ResetButtonSize; + Rect offsetRect = EditorGUILayout.GetControlRect(); + Rect offsetVec2Rect = offsetRect; + offsetVec2Rect.x += tillingOffsetLabelWidth; + offsetVec2Rect.width -= tillingOffsetLabelWidth; + offsetVec2Rect.width -= ResetTool.ResetButtonSize; + offsetVec2Rect.width -= 2f; + Rect offsetResetButtonRect = offsetRect; + offsetResetButtonRect.x = offsetResetButtonRect.x + offsetResetButtonRect.width - ResetTool.ResetButtonSize; + offsetResetButtonRect.width = ResetTool.ResetButtonSize; + EditorGUILayout.EndVertical(); + EditorGUILayout.EndHorizontal(); + + Texture texture = textureProperty.textureValue; + Action drawTextureEndChangeCheck = () => + { + textureProperty.textureValue = texture; + ResetTool.CheckOnValueChange((label,texturePropertyPack.property.name)); + }; + EditorGUI.BeginChangeCheck(); + texture = (Texture)EditorGUI.ObjectField(textureRect, texture, typeof(Texture2D), false); + if (EditorGUI.EndChangeCheck()) + { + drawTextureEndChangeCheck(); + } + ResetTool.DrawResetModifyButton(textureResetButtonRect,(label,texturePropertyPack.name),texturePropertyPack,resetAction: () => + { + texture = null; + },onValueChangedCallBack:drawTextureEndChangeCheck); + ResetTool.EndResetModifyButtonScope(); + + if (drawScaleOffset) + { + DrawScaleOffset(texturePropertyPack, tillingRect, tillingVec2Rect, tillingResetButtonRect, offsetRect, + offsetVec2Rect, offsetResetButtonRect); + } + return texture; + } + + static float indent => (float) EditorGUI.indentLevel * 15f; + public void TextureScaleOffsetProperty(string texturePropertyName,bool isVectorProp = false) + { + ShaderPropertyPack texturePropertyPack = ShaderPropertyPacksDic[texturePropertyName]; + // EditorGUILayout.BeginHorizontal(); + Rect tillingRect = EditorGUILayout.GetControlRect(); + // EditorGUILayout.EndHorizontal(); + Rect tillingLabelRect = new Rect(tillingRect.x + indent, tillingRect.y, EditorGUIUtility.labelWidth - indent, tillingRect.height); + tillingLabelRect.width = EditorGUIUtility.labelWidth; + Rect tillingVec2Rect = tillingRect; + tillingVec2Rect.x += tillingLabelRect.width; + tillingVec2Rect.x -= indent; + tillingVec2Rect.width -= 3f; + tillingVec2Rect.width -= tillingLabelRect.width; + tillingVec2Rect.width += indent; + tillingVec2Rect.width -= ResetTool.ResetButtonSize; + Rect tillingResetButtonRect = tillingRect; + tillingResetButtonRect.x = tillingResetButtonRect.x + tillingResetButtonRect.width - ResetTool.ResetButtonSize; + tillingResetButtonRect.width = ResetTool.ResetButtonSize; + + + Rect offsetRect = EditorGUILayout.GetControlRect(); + Rect offsetLabelRect = new Rect(offsetRect.x + indent, offsetRect.y, EditorGUIUtility.labelWidth - indent, offsetRect.height); + offsetLabelRect.width = EditorGUIUtility.labelWidth; + Rect offsetVec2Rect = offsetRect; + offsetVec2Rect.x += offsetLabelRect.width; + offsetVec2Rect.x -= indent; + offsetVec2Rect.width -= 3f; + offsetVec2Rect.width -= offsetLabelRect.width; + offsetVec2Rect.width += indent; + offsetVec2Rect.width -= ResetTool.ResetButtonSize; + Rect offsetResetButtonRect = offsetRect; + offsetResetButtonRect.x = offsetResetButtonRect.x + offsetResetButtonRect.width - ResetTool.ResetButtonSize; + offsetResetButtonRect.width = ResetTool.ResetButtonSize; + + DrawScaleOffset(texturePropertyPack,tillingLabelRect,tillingVec2Rect,tillingResetButtonRect,offsetLabelRect,offsetVec2Rect,offsetResetButtonRect,isVectorProp); + + } + + public void DrawScaleOffset(ShaderPropertyPack texturePropertyPack, Rect tillingRect, Rect tillingVec2Rect, + Rect tillingResetButtonRect, Rect offsetRect, Rect offsetVec2Rect, Rect offsetResetButtonRect,bool isVectorProp = false) + { + MaterialProperty textureProperty = texturePropertyPack.property; + Vector4 tillingOffset; + if (isVectorProp) + { + tillingOffset = textureProperty.vectorValue; + } + else + { + tillingOffset = textureProperty.textureScaleAndOffset; + } + string tillingLabel = "Tilling"; + var tillingTuple = (tillingLabel, textureProperty.name + "_ST"); + GUI.Label(tillingRect,tillingLabel); + Vector2 tilling = new Vector2(tillingOffset.x, tillingOffset.y); + Action drawTillingEndChangeCheck = () => + { + tillingOffset.x = tilling.x; + tillingOffset.y = tilling.y; + if (isVectorProp) + { + textureProperty.vectorValue = tillingOffset; + } + else + { + textureProperty.textureScaleAndOffset = tillingOffset; + } + ResetTool.CheckOnValueChange(tillingTuple); + + }; + EditorGUI.BeginChangeCheck(); + if (IsPropertyAnimated(tillingTuple.Item2, "x","y") ) + { + GUI.backgroundColor = animatedBackgroundColor; + } + tilling = EditorGUI.Vector2Field(tillingVec2Rect, "", tilling); + GUI.backgroundColor = defaultBackgroundColor; + if (EditorGUI.EndChangeCheck()) + { + drawTillingEndChangeCheck(); + } + + ResetTool.DrawResetModifyButton(tillingResetButtonRect,tillingTuple,texturePropertyPack,resetAction: () => + { + tilling = Vector2.one; + },onValueChangedCallBack:drawTillingEndChangeCheck,VectorValeType.Tilling); + ResetTool.EndResetModifyButtonScope(); + + string offsetLabel = "Offset"; + var offsetTuple = (offsetLabel, textureProperty.name + "_ST"); + GUI.Label(offsetRect,offsetLabel); + Vector2 offset = new Vector2(tillingOffset.z, tillingOffset.w); + Action drawOffsetEndChangeCheck = () => + { + tillingOffset.z = offset.x; + tillingOffset.w = offset.y; + if (isVectorProp) + { + textureProperty.vectorValue = tillingOffset; + } + else + { + textureProperty.textureScaleAndOffset = tillingOffset; + } + ResetTool.CheckOnValueChange(offsetTuple); + + }; + EditorGUI.BeginChangeCheck(); + if (IsPropertyAnimated(offsetTuple.Item2, "z","w")) + { + GUI.backgroundColor = animatedBackgroundColor; + } + offset = EditorGUI.Vector2Field(offsetVec2Rect, "", offset); + GUI.backgroundColor = defaultBackgroundColor; + if (EditorGUI.EndChangeCheck()) + { + drawOffsetEndChangeCheck(); + } + + ResetTool.DrawResetModifyButton(offsetResetButtonRect,offsetTuple,texturePropertyPack,resetAction: () => + { + offset = Vector2.zero; + },onValueChangedCallBack:drawOffsetEndChangeCheck,VectorValeType.Offset); + ResetTool.EndResetModifyButtonScope(); + } + + bool WrapModeFlagHasMixedValue(int wrapModeFlagBitsName, int flagIndex) + { + int tmpWrapMode = 0; + for (int i = 0; i < shaderFlags.Length; i++) + { + if (i == 0) + { + tmpWrapMode = GetWrapModeFlagValue(wrapModeFlagBitsName,flagIndex,shaderFlags[i]); + } + else + { + if (!tmpWrapMode.Equals(GetWrapModeFlagValue(wrapModeFlagBitsName, flagIndex, shaderFlags[i]))) + { + return true; + } + } + } + + return false; + } + + int GetWrapModeFlagValue(int wrapModeFlagBitsName, int flagIndex,ShaderFlagsBase shaderFlag) + { + int tmpWrapMode = shaderFlag.CheckFlagBits(wrapModeFlagBitsName, index: flagIndex) ? 1 : 0; + tmpWrapMode = shaderFlag.CheckFlagBits(wrapModeFlagBitsName << 16, index: flagIndex) + ? tmpWrapMode + 2 + : tmpWrapMode; + return tmpWrapMode; + } + + void SetWrapModeFlagValue(int wrapModeFlagBitsName, int flagIndex,int wrapModeValue) + { + for (int i = 0; i < shaderFlags.Length; i++) + { + switch (wrapModeValue) + { + case 0: + shaderFlags[i].ClearFlagBits(wrapModeFlagBitsName, index: flagIndex); + shaderFlags[i].ClearFlagBits(wrapModeFlagBitsName << 16, index: flagIndex); + break; + case 1: + shaderFlags[i].SetFlagBits(wrapModeFlagBitsName, index: flagIndex); + shaderFlags[i].ClearFlagBits(wrapModeFlagBitsName << 16, index: flagIndex); + break; + case 2: + shaderFlags[i].ClearFlagBits(wrapModeFlagBitsName, index: flagIndex); + shaderFlags[i].SetFlagBits(wrapModeFlagBitsName << 16, index: flagIndex); + break; + case 3: + shaderFlags[i].SetFlagBits(wrapModeFlagBitsName, index: flagIndex); + shaderFlags[i].SetFlagBits(wrapModeFlagBitsName << 16, index: flagIndex); + break; + } + } + } + + public void DrawWrapMode(string texturelabel,int wrapModeFlagBitsName = 0, int flagIndex = 2) + { + bool hasMixedValue = WrapModeFlagHasMixedValue(wrapModeFlagBitsName, flagIndex); + EditorGUI.showMixedValue = hasMixedValue; + string wrapLabel = texturelabel + "循环模式"; + (string, string) wrapNameTuple = (wrapLabel, ""); + + int tmpWrapMode = GetWrapModeFlagValue(wrapModeFlagBitsName, flagIndex,shaderFlags[0]); + Action onWrapModeEndChangeCheck = () => + { + SetWrapModeFlagValue(wrapModeFlagBitsName, flagIndex, tmpWrapMode); + hasMixedValue = WrapModeFlagHasMixedValue(wrapModeFlagBitsName, flagIndex); + ResetTool.CheckOnValueChange(wrapNameTuple); + }; + EditorGUI.BeginChangeCheck(); + EditorGUILayout.BeginHorizontal(); + tmpWrapMode = EditorGUILayout.Popup(new GUIContent(wrapLabel), tmpWrapMode, + Enum.GetNames(typeof(SamplerWarpMode))); + if (EditorGUI.EndChangeCheck()) + { + onWrapModeEndChangeCheck(); + } + ResetTool.DrawResetModifyButton(new Rect(),wrapNameTuple,resetCallBack: () => + { + tmpWrapMode = 0; + },onValueChangedCallBack:onWrapModeEndChangeCheck,() => + { + bool hasModified = GetWrapModeFlagValue(wrapModeFlagBitsName, flagIndex,shaderFlags[0]) != 0 ? true : false; + return hasModified; + }, () => WrapModeFlagHasMixedValue(wrapModeFlagBitsName, flagIndex)); + EditorGUILayout.EndHorizontal(); + ResetTool.EndResetModifyButtonScope(); + } + public void DrawAfterTexture(bool hasTexture, string label, string texturePropertyName, bool drawWrapMode = false, int wrapModeFlagBitsName = 0, int flagIndex = 2, + Action drawBlock = null) + { + EditorGUI.indentLevel++; + EditorGUI.BeginDisabledGroup(!hasTexture); + if (drawWrapMode) + { + DrawWrapMode(label, wrapModeFlagBitsName,flagIndex); + } + + drawBlock?.Invoke(GetProperty(texturePropertyName)); + EditorGUI.indentLevel--; + EditorGUI.EndDisabledGroup(); + } + + + public void DrawPopUp(string label, string propertyName, string[] options, string[] toolTips = null, + Action drawBlock = null,Action drawOnValueChangedBlock = null,bool isSharedGlobalParent = false) + { + MaterialProperty property = GetProperty(propertyName); + if (property == null) return; + EditorGUI.showMixedValue = property.hasMixedValue; + + float mode = property.floatValue; + EditorGUI.BeginChangeCheck(); + GUIContent[] optionGUIContents = new GUIContent[options.Length]; + for (int i = 0; i < optionGUIContents.Length; i++) + { + if (toolTips != null && toolTips.Length == options.Length) + { + optionGUIContents[i] = new GUIContent(options[i], toolTips[i]); + } + else + { + optionGUIContents[i] = new GUIContent(options[i]); + } + } + + Action drawOnValueChanged = () => + { + property.floatValue = mode; + drawOnValueChangedBlock?.Invoke(property); + ResetTool.CheckOnValueChange((label,propertyName)); + }; + + + EditorGUILayout.BeginHorizontal(); + mode = EditorGUILayout.Popup(new GUIContent(label), (int)mode, optionGUIContents); + if (EditorGUI.EndChangeCheck()) + { + drawOnValueChanged.Invoke(); + } + ResetTool.DrawResetModifyButton(new Rect(),(label,propertyName),ShaderPropertyPacksDic[propertyName],resetAction: () => + { + mode = property.floatValue; + },onValueChangedCallBack:drawOnValueChanged); + EditorGUILayout.EndHorizontal(); + + drawBlock?.Invoke(property); + ResetTool.EndResetModifyButtonScope(); + EditorGUI.showMixedValue = false; + + // if (ResetTool.IsInitResetData) + // { + // ResetTool.CheckOnValueChange((label,propertyName));//为什么是在这里验证而不是再ResetTool里。 + // } + } + + public MaterialProperty GetProperty(string propertyName) + { + // foreach (ShaderPropertyPack pack in ShaderPropertyPacks) + // { + // if (pack.name == propertyName) + // { + // return pack.property; + // } + // } + if (ShaderPropertyPacksDic.ContainsKey(propertyName)) + { + return ShaderPropertyPacksDic[propertyName].property; + } + + // Debug.LogError("材质球" + mat.name + "找不到属性" + propertyName, mat); + return null; + } + + bool RenderQueueHasMixedValue() + { + int queue = 0; + for (int i = 0; i < mats.Count; i++) + { + if (i == 0) + { + queue = mats[i].renderQueue; + } + else + { + if (queue != mats[i].renderQueue) + { + return true; + } + } + } + return false; + } + + public void DrawRenderQueue(MaterialProperty queueBiasProp) + { + Rect rect = EditorGUILayout.GetControlRect(); + Rect labelRect = new Rect(rect.x, rect.y, EditorGUIUtility.labelWidth, rect.height); + int queueLabelWidth = 55; + Rect queueLabelRect = new Rect(labelRect.x , labelRect.y, queueLabelWidth, rect.height); + Rect queueNumberRect = new Rect(queueLabelRect.x + queueLabelWidth , queueLabelRect.y,EditorGUIUtility.labelWidth - queueLabelWidth, rect.height); + EditorGUI.LabelField(queueLabelRect, "Queue:" ); + EditorGUI.showMixedValue = RenderQueueHasMixedValue(); + EditorGUI.BeginDisabledGroup(true); + EditorGUI.TextField(queueNumberRect, mats[0].renderQueue.ToString()); + EditorGUI.EndDisabledGroup(); + EditorGUI.showMixedValue = false; + Rect afterLabelRect = GetRectAfterLabelWidth(rect); + int QueueBias = (int)queueBiasProp.floatValue; + EditorGUI.showMixedValue = queueBiasProp.hasMixedValue; + EditorGUI.BeginChangeCheck(); + QueueBias = EditorGUI.IntField(afterLabelRect, "QueueBias:", QueueBias); + if (EditorGUI.EndChangeCheck()) + { + queueBiasProp.floatValue = QueueBias; + } + EditorGUI.showMixedValue = false; + } + + void GuiLine(int i_height = 1) + { + + Rect rect = EditorGUILayout.GetControlRect(false, i_height); + rect.height = i_height; + EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 0.5f)); + + } + + public static float PowerSlider(Rect position, GUIContent label, float value, float leftValue, float rightValue, + float power) + { + var editorGuiType = typeof(EditorGUI); + var methodInfo = editorGuiType.GetMethod( + "PowerSlider", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static, + null, + new[] { typeof(Rect), typeof(GUIContent), typeof(float), typeof(float), typeof(float), typeof(float) }, + null); + if (methodInfo != null) + { + return (float)methodInfo.Invoke(null, + new object[] { position, label, value, leftValue, rightValue, power }); + } + + return leftValue; + } + + + private GradientAlphaKey[] defaultGradientAlphaKey = new GradientAlphaKey[] + { new GradientAlphaKey(1, 0), new GradientAlphaKey(1, 1) }; + + + float RGBLuminance(Color color) + { + return 0.2126f* color.r + 0.7152f * color.g + 0.0722f * color.b; + } + + private bool isUpateGradientPickerCache = false; + + public void DrawGradientUndoPerformed() + { + // Debug.Log("UndoGradient"); + isUpateGradientPickerCache = true; + } + Dictionary<(string,string),bool> gradientsUpdateDic = new Dictionary<(string,string),bool>(); + Dictionary<(string,string),Gradient> gradientsDic = new Dictionary<(string,string),Gradient>(); + + void GetGradientKeyCount(MaterialProperty countProperty, + MaterialProperty[] colorProperties, MaterialProperty[] alphaProperties,out int countPropertyIntValue,out int colorKeysCount,out int alphaKeysCount) + { + + countPropertyIntValue = countProperty.intValue; + if (colorProperties != null && alphaProperties != null) + { + colorKeysCount = countPropertyIntValue & 0xFFFF; + alphaKeysCount = countPropertyIntValue >> 16; + } + else + { + colorKeysCount = countPropertyIntValue; + alphaKeysCount = 2; + } + } + bool GradientPropertyHasMixedValue(MaterialProperty countProperty, + MaterialProperty[] colorProperties = null, MaterialProperty[] alphaProperties = null) + { + + + GetGradientKeyCount(countProperty, colorProperties, alphaProperties,out int countPropertyIntValue, out int colorKeysCount,out int alphaKeysCount); + + bool hasMixedValue = false; + hasMixedValue |= countProperty.hasMixedValue; + if (colorProperties != null) + { + for(int i = 0; i < colorKeysCount; i++) + { + hasMixedValue |= colorProperties[i].hasMixedValue; + } + } + if (alphaProperties != null) + { + for (int i = 0; i < Mathf.CeilToInt(alphaKeysCount/2f); i++) + { + hasMixedValue |= alphaProperties[i].hasMixedValue; + } + } + return hasMixedValue; + + + } + + void GetGradientConditionBool(MaterialProperty[] colorProperties, + MaterialProperty[] alphaProperties, out bool isBlackAndWhiteGradient, + out bool isNoAlphaColorGradient) + { + isBlackAndWhiteGradient = colorProperties == null && alphaProperties != null; + isNoAlphaColorGradient = colorProperties != null && alphaProperties == null; + } + + void SetGradientByProperty(Gradient gradient, MaterialProperty countProperty, + MaterialProperty[] colorProperties = null, MaterialProperty[] alphaProperties = null) + { + GetGradientConditionBool(colorProperties,alphaProperties,out bool isBlackAndWhiteGradient,out bool isNoAlphaColorGradient); + GetGradientKeyCount(countProperty, colorProperties, alphaProperties,out int countPropertyIntValue, out int colorKeysCount,out int alphaKeysCount); + + if (colorProperties != null || isBlackAndWhiteGradient) + { + GradientColorKey[] colorKeys; + if (gradient.colorKeys.Length != colorKeysCount) + { + colorKeys = new GradientColorKey[colorKeysCount]; + } + else + { + colorKeys = gradient.colorKeys; + } + for (int i = 0; i < colorKeysCount; i++) + { + if (isBlackAndWhiteGradient) + { + Vector4 vec = alphaProperties[i / 2].vectorValue; + Color c = Color.white; + if (i % 2 == 0) + { + c.r = vec.x; + c.g = vec.x; + c.b = vec.x; + } + else + { + c.r = vec.z; + c.g = vec.z; + c.b = vec.z; + } + // Debug.Log(i); + // Debug.Log(c); + colorKeys[i].color = c; + colorKeys[i].time = i % 2 == 0 ? vec.y : vec.w; + } + else + { + Color c = colorProperties[i].colorValue; + colorKeys[i].color = c; + colorKeys[i].time = c.a; + } + } + gradient.colorKeys = colorKeys; + } + + if (isBlackAndWhiteGradient || isNoAlphaColorGradient || alphaProperties == null) + { + gradient.alphaKeys = defaultGradientAlphaKey; + } + else + { + + GradientAlphaKey[] alphaKeys; + if (gradient.alphaKeys.Length != alphaKeysCount) + { + alphaKeys = new GradientAlphaKey[alphaKeysCount]; + } + else + { + alphaKeys = gradient.alphaKeys; + } + + for (int i = 0; i < alphaKeysCount ; i++) + { + Vector4 vec = alphaProperties[i / 2].vectorValue; + if (i % 2 == 0) + { + alphaKeys[i].alpha = vec.x; + alphaKeys[i].time = vec.y; + } + else + { + alphaKeys[i].alpha = vec.z; + alphaKeys[i].time = vec.w; + } + } + gradient.alphaKeys = alphaKeys; + + } + } + //如果是黑白Gradient,则取Gradient的颜色的黑白值(这样在面板上可视化比较好) + //如果既有颜色,也有Alpha。则在CountProperty上采取前16位和后16位编码。 + //原则:gradient对象只是一个操作中介。取值应该直接在MatProperty上去,Set值也应该在验证合法后才能Set,不合法应该提出警告。 + public void DrawGradient(bool hdr,ColorSpace colorSpace,string label,int maxCount,string countPropertyName,MaterialProperty[] colorProperties = null,MaterialProperty[] alphaProperties = null) + { + (string,string) nameTuple = (label, countPropertyName); + + + if (isUpateGradientPickerCache) + { + foreach (var keys in gradientsUpdateDic.Keys.ToList()) + { + gradientsUpdateDic[keys] = true; + } + + isUpateGradientPickerCache = false; + } + MaterialProperty countProperty = GetProperty(countPropertyName); + Rect rect = EditorGUILayout.GetControlRect(); + + // var labelRect = new Rect(rect.x + 2f, rect.y, rect.width - 2f, rect.height); + // EditorGUI.LabelField(labelRect,label); + var gradientRect = rect; + gradientRect.width -= ResetTool.ResetButtonSize; + gradientRect.width -= 2f; + var gradientResetButtonRect = rect; + gradientResetButtonRect.x = gradientResetButtonRect.x + gradientResetButtonRect.width - ResetTool.ResetButtonSize; + gradientResetButtonRect.width = ResetTool.ResetButtonSize; + + Gradient gradient; + if (!gradientsDic.ContainsKey(nameTuple)||gradientsUpdateDic[nameTuple]) + { + if (!gradientsDic.ContainsKey(nameTuple)) + { + gradient = new Gradient(); + // gradient.colorSpace = ColorSpace.Gamma; + gradientsDic.Add(nameTuple,gradient); + gradientsUpdateDic.Add(nameTuple,false); + } + else + { + gradient = gradientsDic[nameTuple]; + gradientsUpdateDic[nameTuple] = false; + } + + SetGradientByProperty(gradient,countProperty, colorProperties, alphaProperties); + + GradientReflectionHelper.RefreshGradientData(); + // Debug.Log("----------------SetCurrentGradient------------------"); + } + else + { + gradient = gradientsDic[nameTuple]; + } + + EditorGUI.showMixedValue = GradientPropertyHasMixedValue(countProperty, colorProperties, alphaProperties); + GetGradientKeyCount(countProperty, colorProperties, alphaProperties,out int countPropertyIntValue, out int colorKeysCount,out int alphaKeysCount); + GetGradientConditionBool(colorProperties, alphaProperties,out bool isBlackAndWhiteGradient,out bool isNoAlphaColorGradient); + + EditorGUI.BeginChangeCheck(); + gradient = EditorGUI.GradientField(gradientRect, new GUIContent(label),gradient,hdr,colorSpace); + + Action onGradientEndChangeCheck = () => + { + gradientsUpdateDic[nameTuple] = true; + int countPropertyValue = countPropertyIntValue; + + if (colorProperties != null || isBlackAndWhiteGradient) + { + int finalColorKeysCount = gradient.colorKeys.Length; + if (finalColorKeysCount <= maxCount) + { + if (isBlackAndWhiteGradient) + { + int floatPropertyCount = Mathf.CeilToInt((float)finalColorKeysCount / (2f)); + for (int i = 0; i < floatPropertyCount; i++) + { + Vector4 vec = Vector4.zero; + vec.x = gradient.colorKeys[i*2].color.r; + vec.y = gradient.colorKeys[i*2].time; + if (i * 2 + 1 < gradient.colorKeys.Length) + { + vec.z = gradient.colorKeys[i * 2 + 1].color.r; + vec.w = gradient.colorKeys[i * 2 + 1].time; + } + + alphaProperties[i].vectorValue = vec; + } + } + else + { + for (int i = 0; i < finalColorKeysCount; i++) + { + + Color c = gradient.colorKeys[i].color; + c.a = gradient.colorKeys[i].time; + colorProperties[i].colorValue = c; + } + } + + countPropertyValue &= (0xFFFF <<16); + countPropertyValue |= finalColorKeysCount; + } + } + + if (!(isBlackAndWhiteGradient || isNoAlphaColorGradient || alphaProperties == null)) + { + int finalAlphaKeysCount = gradient.alphaKeys.Length; + if (finalAlphaKeysCount <= maxCount) + { + int floatPropertyCount = Mathf.CeilToInt((float)finalAlphaKeysCount / (2f)); + for (int i = 0; i < floatPropertyCount; i++) + { + Vector4 vec = Vector4.zero; + vec.x = gradient.alphaKeys[i*2].alpha; + vec.y = gradient.alphaKeys[i*2].time; + if (i * 2 + 1 < gradient.alphaKeys.Length) + { + vec.z = gradient.alphaKeys[i * 2 + 1].alpha; + vec.w = gradient.alphaKeys[i * 2 + 1].time; + } + alphaProperties[i].vectorValue = vec; + } + + countPropertyValue &= (0xFFFF); + int alphaCount = finalAlphaKeysCount << 16; + countPropertyValue |= alphaCount; + } + } + + countProperty.intValue = countPropertyValue; + ResetTool.CheckOnValueChange(nameTuple); + + }; + + if (EditorGUI.EndChangeCheck()) + { + onGradientEndChangeCheck(); + } + + + ResetTool.DrawResetModifyButton(gradientResetButtonRect,nameTuple,resetCallBack: () => + { + ShaderPropertyPack countPropPack = ShaderPropertyPacksDic[countPropertyName]; + + countPropPack.property.intValue = 2; + + if (colorProperties != null) + { + foreach (var colorProp in colorProperties) + { + ShaderPropertyPack colorPropPack = ShaderPropertyPacksDic[colorProp.name]; + colorPropPack.property.colorValue = + shader.GetPropertyDefaultVectorValue(colorPropPack.index); + } + } + + if (alphaProperties != null) + { + foreach (var alphaProps in alphaProperties) + { + ShaderPropertyPack alphaPropPack = ShaderPropertyPacksDic[alphaProps.name]; + alphaPropPack.property.vectorValue = shader.GetPropertyDefaultVectorValue(alphaPropPack.index); + } + } + SetGradientByProperty(gradient,countProperty, colorProperties, alphaProperties); + + },onValueChangedCallBack:onGradientEndChangeCheck, + checkHasMixedValueOnValueChange: () => + GradientPropertyHasMixedValue(countProperty, colorProperties, alphaProperties), + checkHasModifyOnValueChange: () => + { + bool hasModified = false; + ShaderPropertyPack countPropPack = ShaderPropertyPacksDic[countPropertyName]; + + bool hasCountModified = !Mathf.Approximately(mats[0].GetInteger(countPropPack.name),2); + hasModified |= hasCountModified; + if (colorProperties != null) + { + foreach (var colorProp in colorProperties) + { + ShaderPropertyPack colorPropPack = ShaderPropertyPacksDic[colorProp.name]; + hasModified |= mats[0].GetVector(colorPropPack.name) != + shader.GetPropertyDefaultVectorValue(colorPropPack.index); + } + } + + if (alphaProperties != null) + { + foreach (var alphaProps in alphaProperties) + { + ShaderPropertyPack alphaPropPack = ShaderPropertyPacksDic[alphaProps.name]; + Vector4 vec = mats[0].GetVector(alphaPropPack.name); + Vector4 defaultVec = shader.GetPropertyDefaultVectorValue(alphaPropPack.index); + hasModified |= vec != defaultVec; + } + } + return hasModified; + }); + + ResetTool.EndResetModifyButtonScope(); + } + + + + + } + + public enum VectorValeType + { + X,Y,Z,W,XY,ZW,XYZ,XYZW,Tilling,Offset,Undefine + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIHelper.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIHelper.cs.meta new file mode 100644 index 00000000..7ffea5ac --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9279ba81938dc1548b9e9d8297bdcd57 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems.meta new file mode 100644 index 00000000..5967d40c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 947243301cab4804d8df47a42b220c4e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/BlockItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/BlockItem.cs new file mode 100644 index 00000000..f298f85f --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/BlockItem.cs @@ -0,0 +1,88 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class BlockItem : ShaderGUIItem + { + protected readonly ShaderGUIRootItem SharedRootItem; + private readonly ShaderGUIFoldOutHelper _foldOutHelper; + private readonly Func _contentProvider; + + protected virtual GUIStyle TitleStyle => EditorStyles.label; + protected virtual bool DrawSeparatorLine => false; + + public string FoldOutPropertyName { get; } + + public BlockItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string foldOutPropertyName, + Func contentProvider) : base(rootItem, parentItem) + { + SharedRootItem = rootItem; + FoldOutPropertyName = foldOutPropertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + GuiContent = _contentProvider(); + _foldOutHelper = new ShaderGUIFoldOutHelper(rootItem, foldOutPropertyName); + } + + public override void OnGUI() + { + DrawLeadingSpace(); + GetRect(); + _foldOutHelper.DrawFoldOut(LabelRect); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent, TitleStyle); + } + + DrawResetButton(); + EditorGUI.indentLevel++; + if (_foldOutHelper.BeginFadeGroup()) + { + DrawBlock(); + } + _foldOutHelper.EndFadedGroup(); + EditorGUI.indentLevel--; + if (DrawSeparatorLine) + { + Rect rect = ApplyGlobalRectCompensation(LayoutRect(1)); + EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 0.5f)); + } + } + + protected virtual void DrawLeadingSpace() + { + } + + public override void DrawBlock() + { + for (int i = 0; i < ChildrenItemList.Count; i++) + { + ChildrenItemList[i].OnGUI(); + } + } + } + + public class BigBlockItem : BlockItem + { + protected override GUIStyle TitleStyle => EditorStyles.boldLabel; + protected override bool DrawSeparatorLine => true; + + public BigBlockItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string foldOutPropertyName, + Func contentProvider) : base(rootItem, parentItem, foldOutPropertyName, contentProvider) + { + } + + protected override void DrawLeadingSpace() + { + LayoutSpace(); + } + } + +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/BlockItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/BlockItem.cs.meta new file mode 100644 index 00000000..ec1259a0 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/BlockItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d07eceb7cee2d8b46ab0f6f62c4f82e5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ColorItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ColorItem.cs new file mode 100644 index 00000000..94375fdd --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ColorItem.cs @@ -0,0 +1,190 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class ColorItem : ShaderGUIItem + { + private const float ColorFieldLeftInset = EditorGUIIndentWidth; + + private readonly Func _contentProvider; + private readonly Func _isVisible; + + public ColorItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(false); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + Color color = PropertyInfo.Property.colorValue; + bool hdr = ShaderGUIUnityCompat.HasHdrFlag(PropertyInfo.Property); + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = PropertyInfo.Property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + Rect colorRect = GetLabeledColorFieldRect(ControlRect); + bool animatedScope = BeginAnimatedPropertyBackground(colorRect, PropertyInfo.Property); + using (new EditorGUIIndentLevelScope(0)) + { + color = EditorGUI.ColorField(colorRect, GUIContent.none, color, true, true, hdr); + } + EndAnimatedPropertyBackground(animatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + PropertyInfo.Property.colorValue = color; + OnEndChange(); + } + } + + DrawResetButton(); + DrawBlock(); + } + + internal static Rect GetNoLabelColorFieldRect(Rect rect) + { + rect.x += ColorFieldLeftInset; + rect.width = Mathf.Max(0f, rect.width - ColorFieldLeftInset); + return rect; + } + + internal static Rect GetLabeledColorFieldRect(Rect rect) + { + float leftPadding = EditorStyles.colorField.padding.left + ColorFieldLeftInset +1f; + rect.x -= leftPadding; + rect.width += leftPadding; + return rect; + } + } + + public class ColorLineItem : ShaderGUIItem + { + private readonly Func _contentProvider; + private readonly bool _showLabel; + private readonly Func _isVisible; + + public ColorLineItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + bool showLabel, + Func contentProvider = null, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _showLabel = showLabel; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _showLabel ? _contentProvider() : GUIContent.none; + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + Draw(ApplyGlobalRectCompensation(LayoutRect())); + DrawBlock(); + } + + public void Draw(Rect rect) + { + BaseRect = rect; + + if (_showLabel) + { + SplitLineRect(rect, out LabelRect, out ControlRect, out ResetRect, false); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + } + else + { + LabelRect = new Rect(rect.x, rect.y, 0f, rect.height); + SplitControlAndResetRect(rect, out ControlRect, out ResetRect, false); + } + + MaterialProperty property = PropertyInfo.Property; + Color color = property.colorValue; + bool hdr = ShaderGUIUnityCompat.HasHdrFlag(property); + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + Rect colorRect = _showLabel + ? ColorItem.GetLabeledColorFieldRect(ControlRect) + : ColorItem.GetNoLabelColorFieldRect(ControlRect); + bool animatedScope = BeginAnimatedPropertyBackground(colorRect, property); + using (new EditorGUIIndentLevelScope(0)) + { + color = EditorGUI.ColorField(colorRect, GUIContent.none, color, true, true, hdr); + } + EndAnimatedPropertyBackground(animatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + property.colorValue = color; + OnEndChange(); + } + } + + DrawResetButton(); + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + if (!isCallByChild) + { + bool isDefaultValue = true; + if (PropertyInfo != null) + { + Vector4 defaultColor = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + isDefaultValue = !PropertyInfo.Property.hasMixedValue && + Approximately(PropertyInfo.Property.colorValue, defaultColor); + } + + if (isDefaultValue == PropertyIsDefaultValue) + { + return; + } + + PropertyIsDefaultValue = isDefaultValue; + } + + HasModified = !PropertyIsDefaultValue; + foreach (ShaderGUIItem childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + + ParentItem?.CheckIsPropertyModified(true); + } + + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ColorItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ColorItem.cs.meta new file mode 100644 index 00000000..4335372c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ColorItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 31b44f82d6184d46b683b144f9b5f517 +timeCreated: 1777032000 diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/GradientItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/GradientItem.cs new file mode 100644 index 00000000..bc67b15b --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/GradientItem.cs @@ -0,0 +1,533 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NBShaderEditor +{ + public class GradientItem : ShaderGUIItem + { + private static bool s_UndoRedoRegistered; + private static int s_UndoRedoVersion; + + private readonly Func _contentProvider; + private readonly string[] _colorPropertyNames; + private readonly string[] _alphaPropertyNames; + private readonly int _maxCount; + private readonly bool _hdr; + private readonly ColorSpace _colorSpace; + private readonly Func _isVisible; + + private ShaderPropertyInfo[] _colorPropertyInfos; + private ShaderPropertyInfo[] _alphaPropertyInfos; + private readonly Gradient _gradient = new Gradient(); + private GradientColorKey[] _colorKeys = Array.Empty(); + private GradientAlphaKey[] _alphaKeys = Array.Empty(); + private bool _gradientCacheDirty = true; + private int _lastUndoRedoVersion = -1; + + public GradientItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string countPropertyName, + int maxCount, + string[] colorPropertyNames, + string[] alphaPropertyNames, + Func contentProvider, + bool hdr = false, + ColorSpace colorSpace = ColorSpace.Gamma, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = countPropertyName; + _maxCount = Mathf.Max(2, maxCount); + _colorPropertyNames = colorPropertyNames ?? Array.Empty(); + _alphaPropertyNames = alphaPropertyNames ?? Array.Empty(); + _contentProvider = contentProvider ?? (() => GUIContent.none); + _hdr = hdr; + _colorSpace = colorSpace; + _isVisible = isVisible; + GuiContent = _contentProvider(); + EnsureUndoRedoRegistered(); + CacheProperties(); + InitTriggerByChild(); + } + + private static void EnsureUndoRedoRegistered() + { + if (s_UndoRedoRegistered) + { + return; + } + + Undo.undoRedoPerformed += OnUndoRedoPerformed; + s_UndoRedoRegistered = true; + } + + private static void OnUndoRedoPerformed() + { + s_UndoRedoVersion++; + } + + private void CacheProperties() + { + _colorPropertyInfos = new ShaderPropertyInfo[_colorPropertyNames.Length]; + for (int i = 0; i < _colorPropertyNames.Length; i++) + { + if (RootItem.PropertyInfoDic.TryGetValue(_colorPropertyNames[i], out ShaderPropertyInfo info)) + { + _colorPropertyInfos[i] = info; + } + } + + _alphaPropertyInfos = new ShaderPropertyInfo[_alphaPropertyNames.Length]; + for (int i = 0; i < _alphaPropertyNames.Length; i++) + { + if (RootItem.PropertyInfoDic.TryGetValue(_alphaPropertyNames[i], out ShaderPropertyInfo info)) + { + _alphaPropertyInfos[i] = info; + } + } + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + Gradient gradient = GetCachedGradient(); + using (ParentControlDisabledScope()) + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = GradientPropertyHasMixedValue(); + bool animatedScope = BeginAnimatedPropertyBackground(ControlRect, PropertyInfo.Property); + using (new EditorGUIIndentLevelScope(0)) + { + gradient = EditorGUI.GradientField(ControlRect, GUIContent.none, gradient, _hdr, _colorSpace); + } + EndAnimatedPropertyBackground(animatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + WriteGradient(gradient); + MarkGradientCacheDirty(); + OnEndChange(); + } + } + + DrawResetButton(); + } + + private Gradient GetCachedGradient() + { + if (_lastUndoRedoVersion != s_UndoRedoVersion) + { + _lastUndoRedoVersion = s_UndoRedoVersion; + MarkGradientCacheDirty(); + } + + if (_gradientCacheDirty) + { + ReadGradient(); + _gradientCacheDirty = false; + GradientReflectionHelper.RefreshGradientData(); + } + + return _gradient; + } + + private void MarkGradientCacheDirty() + { + _gradientCacheDirty = true; + } + + private void ReadGradient() + { + bool hasColorProperties = _colorPropertyInfos.Length > 0; + bool hasAlphaProperties = _alphaPropertyInfos.Length > 0; + bool isBlackAndWhiteGradient = !hasColorProperties && hasAlphaProperties; + GetGradientKeyCounts(out int colorKeyCount, out int alphaKeyCount); + + if (_colorKeys.Length != colorKeyCount) + { + _colorKeys = new GradientColorKey[colorKeyCount]; + } + + if (_alphaKeys.Length != alphaKeyCount) + { + _alphaKeys = new GradientAlphaKey[alphaKeyCount]; + } + + for (int i = 0; i < colorKeyCount; i++) + { + Color color = Color.white; + float colorTime = colorKeyCount == 1 ? 0f : i / (float)(colorKeyCount - 1); + if (isBlackAndWhiteGradient) + { + TryReadBlackAndWhiteKey(i, ref color, ref colorTime); + } + else if (i < _colorPropertyInfos.Length && _colorPropertyInfos[i] != null) + { + Color packed = _colorPropertyInfos[i].Property.colorValue; + color = packed; + colorTime = packed.a; + } + + _colorKeys[i] = new GradientColorKey(color, colorTime); + } + + for (int i = 0; i < alphaKeyCount; i++) + { + float alpha = 1f; + float alphaTime = alphaKeyCount == 1 ? 0f : i / (float)(alphaKeyCount - 1); + if (!isBlackAndWhiteGradient && hasAlphaProperties) + { + TryReadAlphaKey(i, ref alpha, ref alphaTime); + } + + _alphaKeys[i] = new GradientAlphaKey(alpha, alphaTime); + } + + _gradient.SetKeys(_colorKeys, _alphaKeys); + } + + private void GetGradientKeyCounts(out int colorKeyCount, out int alphaKeyCount) + { + int countValue = PropertyInfo.Property.intValue; + bool hasColorProperties = _colorPropertyInfos.Length > 0; + bool hasAlphaProperties = _alphaPropertyInfos.Length > 0; + + if (hasColorProperties && hasAlphaProperties) + { + colorKeyCount = countValue & 0xFFFF; + alphaKeyCount = countValue >> 16; + } + else + { + colorKeyCount = countValue; + alphaKeyCount = 2; + } + + } + + private void TryReadBlackAndWhiteKey(int index, ref Color color, ref float time) + { + int vectorIndex = index / 2; + int componentIndex = index % 2; + if (vectorIndex >= _alphaPropertyInfos.Length || _alphaPropertyInfos[vectorIndex] == null) + { + return; + } + + Vector4 packed = _alphaPropertyInfos[vectorIndex].Property.vectorValue; + float value = componentIndex == 0 ? packed.x : packed.z; + time = componentIndex == 0 ? packed.y : packed.w; + color = new Color(value, value, value, 1f); + } + + private void TryReadAlphaKey(int index, ref float alpha, ref float time) + { + int vectorIndex = index / 2; + int componentIndex = index % 2; + if (vectorIndex >= _alphaPropertyInfos.Length || _alphaPropertyInfos[vectorIndex] == null) + { + return; + } + + Vector4 packed = _alphaPropertyInfos[vectorIndex].Property.vectorValue; + if (componentIndex == 0) + { + alpha = packed.x; + time = packed.y; + } + else + { + alpha = packed.z; + time = packed.w; + } + } + + private void WriteGradient(Gradient gradient) + { + bool hasColorProperties = _colorPropertyInfos.Length > 0; + bool hasAlphaProperties = _alphaPropertyInfos.Length > 0; + bool isBlackAndWhiteGradient = !hasColorProperties && hasAlphaProperties; + int countPropertyValue = PropertyInfo.Property.intValue; + + if (isBlackAndWhiteGradient) + { + int finalColorKeyCount = gradient.colorKeys.Length; + if (finalColorKeyCount <= _maxCount) + { + WriteBlackAndWhiteGradient(gradient, finalColorKeyCount); + PropertyInfo.Property.intValue = finalColorKeyCount; + } + + return; + } + + if (hasColorProperties) + { + int finalColorKeyCount = gradient.colorKeys.Length; + if (finalColorKeyCount <= _maxCount) + { + WriteColorKeys(gradient, finalColorKeyCount); + countPropertyValue &= 0xFFFF << 16; + countPropertyValue |= finalColorKeyCount; + } + } + + if (!isBlackAndWhiteGradient && hasAlphaProperties) + { + int finalAlphaKeyCount = gradient.alphaKeys.Length; + if (finalAlphaKeyCount <= _maxCount) + { + WriteAlphaKeys(gradient, finalAlphaKeyCount); + countPropertyValue &= 0xFFFF; + countPropertyValue |= finalAlphaKeyCount << 16; + } + } + + PropertyInfo.Property.intValue = countPropertyValue; + } + + private void WriteColorKeys(Gradient gradient, int colorKeyCount) + { + for (int i = 0; i < colorKeyCount && i < _colorPropertyInfos.Length; i++) + { + if (_colorPropertyInfos[i] == null) + { + continue; + } + + GradientColorKey key = gradient.colorKeys[i]; + _colorPropertyInfos[i].Property.colorValue = new Color(key.color.r, key.color.g, key.color.b, key.time); + } + } + + private void WriteBlackAndWhiteGradient(Gradient gradient, int colorKeyCount) + { + int vectorCount = Mathf.CeilToInt(colorKeyCount / 2f); + for (int i = 0; i < vectorCount && i < _alphaPropertyInfos.Length; i++) + { + if (_alphaPropertyInfos[i] == null) + { + continue; + } + + Vector4 value = Vector4.zero; + GradientColorKey key0 = gradient.colorKeys[i * 2]; + value.x = key0.color.r; + value.y = key0.time; + if (i * 2 + 1 < colorKeyCount) + { + GradientColorKey key1 = gradient.colorKeys[i * 2 + 1]; + value.z = key1.color.r; + value.w = key1.time; + } + + _alphaPropertyInfos[i].Property.vectorValue = value; + } + } + + private void WriteAlphaKeys(Gradient gradient, int alphaKeyCount) + { + int vectorCount = Mathf.CeilToInt(alphaKeyCount / 2f); + for (int i = 0; i < vectorCount && i < _alphaPropertyInfos.Length; i++) + { + if (_alphaPropertyInfos[i] == null) + { + continue; + } + + Vector4 value = Vector4.zero; + GradientAlphaKey key0 = gradient.alphaKeys[i * 2]; + value.x = key0.alpha; + value.y = key0.time; + if (i * 2 + 1 < alphaKeyCount) + { + GradientAlphaKey key1 = gradient.alphaKeys[i * 2 + 1]; + value.z = key1.alpha; + value.w = key1.time; + } + + _alphaPropertyInfos[i].Property.vectorValue = value; + } + } + + private bool GradientPropertyHasMixedValue() + { + if (PropertyInfo == null || PropertyInfo.Property == null) + { + return false; + } + + GetGradientKeyCounts(out int colorKeyCount, out int alphaKeyCount); + bool hasMixedValue = PropertyInfo.Property.hasMixedValue; + for (int i = 0; i < colorKeyCount && i < _colorPropertyInfos.Length; i++) + { + hasMixedValue |= _colorPropertyInfos[i]?.Property.hasMixedValue == true; + } + + int alphaPropertyCount = Mathf.CeilToInt(alphaKeyCount / 2f); + for (int i = 0; i < alphaPropertyCount && i < _alphaPropertyInfos.Length; i++) + { + hasMixedValue |= _alphaPropertyInfos[i]?.Property.hasMixedValue == true; + } + + return hasMixedValue; + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + if (!isCallByChild) + { + bool isDefaultValue = IsCountDefault(); + for (int i = 0; i < _colorPropertyInfos.Length; i++) + { + isDefaultValue &= IsDefault(_colorPropertyInfos[i]); + } + + for (int i = 0; i < _alphaPropertyInfos.Length; i++) + { + isDefaultValue &= IsDefault(_alphaPropertyInfos[i]); + } + + if (isDefaultValue == PropertyIsDefaultValue) + { + return; + } + + PropertyIsDefaultValue = isDefaultValue; + } + + HasModified = !PropertyIsDefaultValue; + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + ResetCountProperty(); + for (int i = 0; i < _colorPropertyInfos.Length; i++) + { + ResetProperty(_colorPropertyInfos[i]); + } + + for (int i = 0; i < _alphaPropertyInfos.Length; i++) + { + ResetProperty(_alphaPropertyInfos[i]); + } + + PropertyIsDefaultValue = true; + HasModified = false; + MarkGradientCacheDirty(); + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + + private bool IsCountDefault() + { + if (PropertyInfo == null || PropertyInfo.Property == null || PropertyInfo.Property.hasMixedValue) + { + return false; + } + + return PropertyInfo.Property.intValue == GetDefaultInt(PropertyInfo); + } + + private void ResetCountProperty() + { + if (PropertyInfo?.Property == null) + { + return; + } + + PropertyInfo.Property.intValue = GetDefaultInt(PropertyInfo); + } + + private bool IsDefault(ShaderPropertyInfo info) + { + if (info == null || info.Property == null || info.Property.hasMixedValue) + { + return false; + } + + switch (ShaderGUIUnityCompat.GetPropertyType(info.Property)) + { + case ShaderPropertyType.Float: + case ShaderPropertyType.Range: + return Mathf.Approximately(info.Property.floatValue, RootItem.Shader.GetPropertyDefaultFloatValue(info.Index)); + case ShaderPropertyType.Int: + return info.Property.intValue == GetDefaultInt(info); + case ShaderPropertyType.Color: + return Approximately(info.Property.colorValue, RootItem.Shader.GetPropertyDefaultVectorValue(info.Index)); + case ShaderPropertyType.Vector: + return Approximately(info.Property.vectorValue, RootItem.Shader.GetPropertyDefaultVectorValue(info.Index)); + default: + return Mathf.Approximately(info.Property.floatValue, GetDefaultScalar(info)); + } + } + + private void ResetProperty(ShaderPropertyInfo info) + { + if (info == null || info.Property == null) + { + return; + } + + switch (ShaderGUIUnityCompat.GetPropertyType(info.Property)) + { + case ShaderPropertyType.Float: + case ShaderPropertyType.Range: + info.Property.floatValue = RootItem.Shader.GetPropertyDefaultFloatValue(info.Index); + break; + case ShaderPropertyType.Int: + info.Property.intValue = GetDefaultInt(info); + break; + case ShaderPropertyType.Color: + info.Property.colorValue = RootItem.Shader.GetPropertyDefaultVectorValue(info.Index); + break; + case ShaderPropertyType.Vector: + info.Property.vectorValue = RootItem.Shader.GetPropertyDefaultVectorValue(info.Index); + break; + default: + info.Property.floatValue = GetDefaultScalar(info); + break; + } + } + + private float GetDefaultScalar(ShaderPropertyInfo info) + { + try + { + return RootItem.Shader.GetPropertyDefaultFloatValue(info.Index); + } + catch (ArgumentException) + { + return 2f; + } + } + + private int GetDefaultInt(ShaderPropertyInfo info) + { + try + { + return GetShaderPropertyDefaultIntValue(RootItem.Shader, info.Index); + } + catch (ArgumentException) + { + return Mathf.RoundToInt(GetDefaultScalar(info)); + } + } + + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/GradientItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/GradientItem.cs.meta new file mode 100644 index 00000000..007942db --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/GradientItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17810b41ec32488faa9fbceaaf8b8fd5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/HelpBoxItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/HelpBoxItem.cs new file mode 100644 index 00000000..34aaa862 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/HelpBoxItem.cs @@ -0,0 +1,37 @@ +using System; +using UnityEditor; + +namespace NBShaderEditor +{ + public class HelpBoxItem : ShaderGUIItem + { + private readonly MessageType _messageType; + private readonly Func _messageProvider; + private readonly Func _isVisible; + + public HelpBoxItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + Func messageProvider, + MessageType messageType = MessageType.Info, + Func isVisible = null) : base(rootItem, parentItem) + { + _messageProvider = messageProvider ?? (() => string.Empty); + _messageType = messageType; + _isVisible = isVisible; + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + using (ParentControlDisabledScope()) + { + DrawLayoutHelpBox(_messageProvider(), _messageType); + } + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/HelpBoxItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/HelpBoxItem.cs.meta new file mode 100644 index 00000000..33baf2c1 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/HelpBoxItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6c516e0fb3014df8b96bce4e0925cb45 +timeCreated: 1777032000 diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/RenderQueueItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/RenderQueueItem.cs new file mode 100644 index 00000000..7b4979b7 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/RenderQueueItem.cs @@ -0,0 +1,51 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class RenderQueueItem : ShaderGUIFloatItem + { + private readonly Func _contentProvider; + private readonly Action _onQueueChanged; + private readonly Func _isVisible; + + public RenderQueueItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + Func contentProvider, + Action onQueueChanged = null, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _onQueueChanged = onQueueChanged; + _isVisible = isVisible; + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + base.OnGUI(); + } + + public override void OnEndChange() + { + base.OnEndChange(); + _onQueueChanged?.Invoke(); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + base.ExecuteReset(isCallByParent); + _onQueueChanged?.Invoke(); + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/RenderQueueItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/RenderQueueItem.cs.meta new file mode 100644 index 00000000..5909c59f --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/RenderQueueItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5caca15eb8794602ae6029d798cb5f1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/SectionLabelItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/SectionLabelItem.cs new file mode 100644 index 00000000..8dd55c6c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/SectionLabelItem.cs @@ -0,0 +1,37 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class SectionLabelItem : ShaderGUIItem + { + private readonly Func _contentProvider; + private readonly Func _isVisible; + + public SectionLabelItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + LayoutSpace(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(ApplyGlobalRectCompensation(LayoutRect()), GuiContent, EditorStyles.boldLabel); + } + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/SectionLabelItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/SectionLabelItem.cs.meta new file mode 100644 index 00000000..df61070f --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/SectionLabelItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75c41d424c5e4203992222069d060bc6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFloatItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFloatItem.cs new file mode 100644 index 00000000..57e527f4 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFloatItem.cs @@ -0,0 +1,394 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class ShaderGUIFloatItem:ShaderGUIItem + { + private readonly Func _isVisible; + + public ShaderGUIFloatItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem, Func isVisible = null) : + base(rootItem, parentItem: parentItem) + { + _isVisible = isVisible; + base.InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + base.OnGUI(); + } + + public override void DrawController() + { + float value = DraggableLabelFloat.Handle(LabelRect, PropertyInfo.Property.floatValue, sensitivity: -1f);//拖动Label控件可以操作Float参数 + value = EditorGUI.FloatField(ControlRect, value); + SetFloatIfDifferent(PropertyInfo.Property, value); + } + + } + + public class ShaderGUISliderItem:ShaderGUIItem + { + public float Min = 0; + public float Max = 1; + public string RangePropertyName; + ShaderPropertyInfo _rangePropertyInfo; + private readonly Func _isVisible; + private const float SliderFrontGap = 5f; + private const float SliderBackGap = 2f; + private const float RangeFieldWidth = 30f; + + public override void InitTriggerByChild() + { + if (RangePropertyName != null) + { + _rangePropertyInfo = RootItem.PropertyInfoDic[RangePropertyName]; + Min = _rangePropertyInfo.Property.vectorValue.x; + Max = _rangePropertyInfo.Property.vectorValue.y; + } + base.InitTriggerByChild(); + } + + public ShaderGUISliderItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem, Func isVisible = null) : + base(rootItem, parentItem: parentItem) + { + _isVisible = isVisible; + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + if (_rangePropertyInfo == null) + { + base.OnGUI(); + return; + } + + GetRect(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + using (ParentControlDisabledScope()) + { + EditorGUI.BeginChangeCheck(); + using (new EditorGUIIndentLevelScope(0)) + { + DrawController(); + } + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + OnEndChange(); + } + } + DrawResetButton(); + DrawBlock(); + } + + public override void DrawController() + { + if (_rangePropertyInfo != null) + { + Rect minRect = ControlRect; + minRect.width = RangeFieldWidth; + Rect maxRect = ControlRect; + maxRect.x = ControlRect.xMax - RangeFieldWidth; + maxRect.width = RangeFieldWidth; + Rect sliderRect = ControlRect; + sliderRect.x = minRect.xMax + SliderFrontGap; + sliderRect.width = Mathf.Max(0f, maxRect.x - sliderRect.x - SliderBackGap + EditorGUI.indentLevel * UnityEditorGUIIndentWidth); + + RangeVecHasMixedValue(out bool minValueHasMixed,out bool maxValueHasMixed); + + Vector4 rangeVector = _rangePropertyInfo.Property.vectorValue; + float min = rangeVector.x; + float max = rangeVector.y; + + EditorGUI.showMixedValue = minValueHasMixed; + bool minAnimatedScope = BeginAnimatedPropertyBackground(minRect, _rangePropertyInfo.Property); + min = EditorGUI.FloatField(minRect, min); + EndAnimatedPropertyBackground(minAnimatedScope); + EditorGUI.showMixedValue = maxValueHasMixed; + bool maxAnimatedScope = BeginAnimatedPropertyBackground(maxRect, _rangePropertyInfo.Property); + max = EditorGUI.FloatField(maxRect, max); + EndAnimatedPropertyBackground(maxAnimatedScope); + rangeVector.x = min; + rangeVector.y = max; + SetVectorIfDifferent(_rangePropertyInfo.Property, rangeVector); + + float sliderMin = Mathf.Min(min, max); + float sliderMax = Mathf.Max(min, max); + float value = DraggableLabelFloat.Handle( + LabelRect, + PropertyInfo.Property.floatValue, + DraggableLabelFloat.GetSensitivityByRange(sliderMin, sliderMax), + sliderMin, + sliderMax); + EditorGUI.showMixedValue = PropertyInfo.Property.hasMixedValue; + bool sliderAnimatedScope = BeginAnimatedPropertyBackground(sliderRect, PropertyInfo.Property); + value = SliderNoIndent(sliderRect, value, sliderMin, sliderMax); + EndAnimatedPropertyBackground(sliderAnimatedScope); + + SetFloatIfDifferent(PropertyInfo.Property, Mathf.Clamp(value, sliderMin, sliderMax)); + EditorGUI.showMixedValue = false; + + } + else + { + float value = DraggableLabelFloat.Handle( + LabelRect, + PropertyInfo.Property.floatValue, + DraggableLabelFloat.GetSensitivityByRange(Min, Max), + Min, + Max); + value = EditorGUI.Slider(ControlRect, value,Min,Max); + SetFloatIfDifferent(PropertyInfo.Property, value); + } + } + + private static float SliderNoIndent(Rect rect, float value, float min, float max) + { + int indentLevel = EditorGUI.indentLevel; + try + { + EditorGUI.indentLevel = 0; + return EditorGUI.Slider(rect, value, min, max); + } + finally + { + EditorGUI.indentLevel = indentLevel; + } + } + + void RangeVecHasMixedValue( out bool minValueHasMixed, out bool maxValueHasMixed) + { + minValueHasMixed = false; + maxValueHasMixed = false; + if (RootItem.Mats.Count > 1) + { + MaterialProperty rangeProperty = _rangePropertyInfo.Property; + float minValue = 0; + float maxValue = 0; + for (int i = 0; i < RootItem.Mats.Count; i++) + { + Vector4 rangeVec = RootItem.Mats[i].GetVector(RangePropertyName); + if (i == 0) + { + minValue = rangeVec.x; + maxValue = rangeVec.y; + } + else + { + if (!Mathf.Approximately(minValue, rangeVec.x)) + { + minValueHasMixed = true; + } + + if (!Mathf.Approximately(maxValue, rangeVec.y)) + { + maxValueHasMixed = true; + } + } + } + } + } + + bool RangePropIsDefaultValue() + { + MaterialProperty rangeProperty = _rangePropertyInfo.Property; + return rangeProperty.vectorValue == RootItem.Shader.GetPropertyDefaultVectorValue(_rangePropertyInfo.Index) && !rangeProperty.hasMixedValue; + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + if (RangePropertyName != null) + { + if (!isCallByChild) //只有自身Reset了,才需要查询自己的状态是否正确 + { + bool isDefaultValue = true; + + float defaultValue = RootItem.Shader.GetPropertyDefaultFloatValue(PropertyInfo.Index); + isDefaultValue = Mathf.Approximately(PropertyInfo.Property.floatValue, defaultValue); + Vector4 defaultRangeVec = RootItem.Shader.GetPropertyDefaultVectorValue(_rangePropertyInfo.Index); + isDefaultValue &= _rangePropertyInfo.Property.vectorValue == defaultRangeVec; + base.CheckIsPropertyModified(isCallByChild); + if (isDefaultValue == PropertyIsDefaultValue) + { + return; //如果状态没有改变,就不需要做任何操作 + } + else + { + PropertyIsDefaultValue = isDefaultValue; + } + } + + HasModified = !PropertyIsDefaultValue; + foreach (var childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + + ParentItem?.CheckIsPropertyModified(true); + } + else + { + base.CheckIsPropertyModified(isCallByChild); + } + + } + + public override void ExecuteReset(bool isCallByParent = false) + { + if (RangePropertyName != null) + { + PropertyInfo.Property.floatValue = RootItem.Shader.GetPropertyDefaultFloatValue(PropertyInfo.Index); + _rangePropertyInfo.Property.vectorValue = + RootItem.Shader.GetPropertyDefaultVectorValue(_rangePropertyInfo.Index); + PropertyIsDefaultValue = true; + + foreach (var childItem in ChildrenItemList) + { + childItem.ExecuteReset(true); + } + + HasModified = false; + if (!isCallByParent) //直接由用户触发重置 + { + ParentItem?.CheckIsPropertyModified(true); + } + } + else + { + base.ExecuteReset(isCallByParent); + } + } + } + + //用于滑动控制Label的方案。 + // DraggableLabelFloat.cs + public static class DraggableLabelFloat + { + // 为每个控件实例缓存一次拖拽状态 + private static readonly System.Collections.Generic.Dictionary s_Drag = + new System.Collections.Generic.Dictionary(); + private class DragState + { + public float startValue; + public float dragX; // 累计水平位移(单位:像素) + } + + public static float Handle(Rect labelRect, float value, float sensitivity = -1f, float? min = null, float? max = null) + { + if (!GUI.enabled) + { + return value; + } + + EditorGUIUtility.AddCursorRect(labelRect, MouseCursor.SlideArrow); + + int id = GUIUtility.GetControlID(FocusType.Passive, labelRect); + Event e = Event.current; + + switch (e.GetTypeForControl(id)) + { + case EventType.MouseDown: + if (labelRect.Contains(e.mousePosition) && e.button == 0) + { + GUIUtility.hotControl = id; + e.Use(); + EditorGUIUtility.SetWantsMouseJumping(1); + + s_Drag[id] = new DragState + { + startValue = value, + dragX = 0f + }; + } + break; + + case EventType.MouseDrag: + if (GUIUtility.hotControl == id && s_Drag.TryGetValue(id, out var st)) + { + // 关键:使用 Event.delta 累加位移,兼容越界/跳回 + st.dragX += e.delta.x; + + float baseSens = sensitivity > 0f + ? sensitivity + : 0.003f * Mathf.Max(1f, Mathf.Abs(st.startValue)); + + float modifier = 1f; + if (e.shift) modifier *= 0.1f; + if (e.control || e.command) modifier *= 10f; + + float accel = 1f + 0.15f * Mathf.Clamp01(Mathf.Abs(st.dragX) / 50f); + + float newValue = st.startValue + st.dragX * baseSens * modifier * accel; + + if (min.HasValue) newValue = Mathf.Max(min.Value, newValue); + if (max.HasValue) newValue = Mathf.Min(max.Value, newValue); + + if (!float.IsNaN(newValue) && !float.IsInfinity(newValue) && !Mathf.Approximately(newValue, value)) + { + GUI.changed = true; + value = newValue; + } + + e.Use(); + } + break; + + case EventType.MouseUp: + if (GUIUtility.hotControl == id) + { + GUIUtility.hotControl = 0; + EditorGUIUtility.SetWantsMouseJumping(0); + s_Drag.Remove(id); + e.Use(); + } + break; + + case EventType.KeyDown: + // 可选:ESC 取消拖拽并还原 + if (GUIUtility.hotControl == id && e.keyCode == KeyCode.Escape && s_Drag.TryGetValue(id, out var st2)) + { + value = st2.startValue; + GUI.changed = true; + + GUIUtility.hotControl = 0; + EditorGUIUtility.SetWantsMouseJumping(0); + s_Drag.Remove(id); + e.Use(); + } + break; + } + + return value; + } + + public static float GetSensitivityByRange(float min, float max) + { + float range = Mathf.Abs(max - min); + if (float.IsNaN(range) || float.IsInfinity(range) || Mathf.Approximately(range, 0f)) + { + return -1f; + } + + return range * 0.003f; + } + + } + +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFloatItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFloatItem.cs.meta new file mode 100644 index 00000000..6afc00ec --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFloatItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b82b6bb5065f449f98cdba68daa4c16f +timeCreated: 1758462240 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFoldOutItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFoldOutItem.cs new file mode 100644 index 00000000..1568f978 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFoldOutItem.cs @@ -0,0 +1,127 @@ +using UnityEditor; +using UnityEngine; +using UnityEditor.AnimatedValues; + +namespace NBShaderEditor +{ + + public class ShaderGUIFoldOutHelper + { + private const float FoldOutAnimationSpeed = 10f; + + public ShaderGUIFoldOutHelper(ShaderGUIRootItem rootItem, string foldOutPropertyName) + { + _rootItem = rootItem; + _propertyName = foldOutPropertyName; + _propertyInfo = _rootItem.PropertyInfoDic[_propertyName]; + + bool isOpen = _propertyInfo.Property.floatValue > 0.5f; + animBool.value = isOpen; + animBool.target = isOpen; + animBool.valueChanged.AddListener(rootItem.MatEditor.Repaint); + animBool.speed = FoldOutAnimationSpeed; + } + + private ShaderGUIRootItem _rootItem; + private string _propertyName; + private AnimBool animBool = new AnimBool(); + + private ShaderPropertyInfo _propertyInfo; + + public bool BeginFadedGroup(Rect labelRect) + { + DrawFoldOut(labelRect); + return BeginFadeGroup(); + } + + public bool BeginFadeGroup() + { + return animBool.faded > 0.0001f; + } + + public bool DrawFoldOut(Rect labelRect) + { + Rect foldOutRect = MakeFoldOutRect(labelRect); + bool isOpen = _propertyInfo.Property.floatValue > 0.5f; + isOpen = GUI.Toggle(foldOutRect, isOpen, GUIContent.none, EditorStyles.foldout); + SetOpen(isOpen); + return isOpen; + } + + public bool DrawFoldOutLabel(Rect labelRect, GUIContent content, GUIStyle style) + { + Rect foldOutRect = MakeFoldOutRect(labelRect); + bool isOpen = _propertyInfo.Property.floatValue > 0.5f; + isOpen = GUI.Toggle(foldOutRect, isOpen, content, style ?? EditorStyles.foldout); + SetOpen(isOpen); + return isOpen; + } + + public void SetOpen(bool isOpen) + { + if (animBool.target != isOpen) + { + animBool.target = isOpen; + } + + float value = isOpen ? 1f : 0f; + if (!Mathf.Approximately(_propertyInfo.Property.floatValue, value)) + { + _propertyInfo.Property.floatValue = value; + } + } + + private static Rect MakeFoldOutRect(Rect labelRect) + { + Rect foldOutRect = labelRect; + foldOutRect.x = ShaderGUIItem.GetEditorLabelTextX(labelRect) - ShaderGUIItem.FoldOutArrowWidth; + foldOutRect.width = Mathf.Max(0f, labelRect.xMax - foldOutRect.x); + return foldOutRect; + } + + public void EndFadedGroup() + { + } + } + + public class ShaderGUIBigBlockItem:ShaderGUIItem + { + ShaderGUIFoldOutHelper _foldOutHelper; + GUIStyle _boldStyle = new GUIStyle(EditorStyles.boldLabel); + public string FoldOutPropertyName { get; set; } + + public override void InitTriggerByChild() + { + _foldOutHelper = new ShaderGUIFoldOutHelper(RootItem, FoldOutPropertyName); + base.InitTriggerByChild(); + } + + public ShaderGUIBigBlockItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : + base(rootItem, parentItem: parentItem) + { + + } + + public override void OnGUI()//完全覆写 + { + LayoutSpace(); + GetRect(); + DrawResetButton(); + bool isOpen = _foldOutHelper.BeginFadedGroup(LabelRect); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent,_boldStyle); + } + + EditorGUI.indentLevel++; + if (isOpen) + { + DrawBlock(); + } + _foldOutHelper.EndFadedGroup(); + EditorGUI.indentLevel--; + Rect rect = ApplyGlobalRectCompensation(LayoutRect(1)); + EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 0.5f)); + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFoldOutItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFoldOutItem.cs.meta new file mode 100644 index 00000000..44658a1d --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIFoldOutItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6228baa804b041658eaebea96655b431 +timeCreated: 1758373869 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIItem.cs new file mode 100644 index 00000000..c0578ff5 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIItem.cs @@ -0,0 +1,517 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; +using System.Collections.Generic; +namespace NBShaderEditor +{ + public enum MixedBool + { + False = 0, + True = 1, + Mixed = -1 + } + + public class ShaderGUIItem + { + public const float MinLabelWidth = 120f; + public const float LabelWidthRatio = 0.4f; + public const float GlobalRectXOffset = -15f; + public const float GlobalRectWidthExpansion = 15f; + public const float UnityEditorGUIIndentWidth = 15f; + public const float EditorGUIIndentWidth = 10f; + public const float FoldOutArrowWidth = UnityEditorGUIIndentWidth; + public const float ControlResetGap = 3f; + public const float ControlIndentCompensation = 10f; + public ShaderPropertyInfo PropertyInfo; + public ShaderGUIItem ParentItem; + public List ChildrenItemList = new List(); + public ShaderGUIRootItem RootItem; + public string PropertyName; + public GUIContent GuiContent; + private static int _parentControlDisabledDepth; + + public virtual void InitTriggerByChild()//根Child一定要做这个事情 + { + if ( PropertyInfo == null && PropertyName != null) + { + PropertyInfo = RootItem.PropertyInfoDic[PropertyName]; + } + CheckIsPropertyModified(); + } + public ShaderGUIItem(ShaderGUIRootItem rtItem,ShaderGUIItem parentItem=null) + { + RootItem = rtItem; + if (parentItem != null) + { + ParentItem = parentItem; + if (!parentItem.ChildrenItemList.Contains(this)) + { + ParentItem.ChildrenItemList.Add(this); + } + } + } + + public Rect BaseRect; + public Rect LabelRect; + public Rect ControlRect; + public Rect ResetRect; + private static readonly GUIContent TempHelpContent = new GUIContent(); + public static float ResetButtonSize => EditorGUIUtility.singleLineHeight; +#if !UNITY_2022_1_OR_NEWER + private static Material s_ShaderDefaultIntValueMaterial; +#endif + + public static int GetShaderPropertyDefaultIntValue(Shader shader, int propertyIndex) + { +#if UNITY_2022_1_OR_NEWER + return shader.GetPropertyDefaultIntValue(propertyIndex); +#else + if (s_ShaderDefaultIntValueMaterial == null || + s_ShaderDefaultIntValueMaterial.shader != shader) + { + if (s_ShaderDefaultIntValueMaterial != null) + { + UnityEngine.Object.DestroyImmediate(s_ShaderDefaultIntValueMaterial); + } + + // Unity 2021.3 has no int default API; use one hidden material as the shader default-value reader. + s_ShaderDefaultIntValueMaterial = new Material(shader) + { + hideFlags = HideFlags.HideAndDontSave + }; + } + + return s_ShaderDefaultIntValueMaterial.GetInteger(shader.GetPropertyName(propertyIndex)); +#endif + } + + public virtual void GetRect(bool applyControlIndentCompensation = true) + { + BaseRect = ApplyGlobalRectCompensation(RootItem.GetControlRect()); + SplitLineRect(BaseRect, out LabelRect, out ControlRect, out ResetRect, applyControlIndentCompensation); + } + + public static Rect ApplyGlobalRectCompensation(Rect rect) + { + rect.x += GlobalRectXOffset; + rect.width = Mathf.Max(0f, rect.width + GlobalRectWidthExpansion); + return rect; + } + + public static Rect ApplyLabelIndentWidth(Rect rect) + { + float indentDelta = EditorGUI.indentLevel * (EditorGUIIndentWidth - UnityEditorGUIIndentWidth); + rect.x += indentDelta; + rect.width = Mathf.Max(0f, rect.width - indentDelta); + return rect; + } + + public static Rect ApplyDirectLabelIndentWidth(Rect rect) + { + float indentOffset = EditorGUI.indentLevel * EditorGUIIndentWidth; + rect.x += indentOffset; + rect.width = Mathf.Max(0f, rect.width - indentOffset); + return rect; + } + + public static float GetEditorLabelTextX(Rect labelRect) + { + return labelRect.x + EditorGUI.indentLevel * UnityEditorGUIIndentWidth; + } + + public static float GetLabelWidth(Rect baseRect) + { + return Mathf.Max(MinLabelWidth, baseRect.width * LabelWidthRatio); + } + + public static void SplitLineRect( + Rect baseRect, + out Rect labelRect, + out Rect controlRect, + out Rect resetRect, + bool applyControlIndentCompensation = true) + { + float labelWidth = GetLabelWidth(baseRect); + labelRect = baseRect; + labelRect.width = labelWidth; + labelRect = ApplyLabelIndentWidth(labelRect); + + Rect controlAndResetRect = baseRect; + controlAndResetRect.x += labelWidth; + controlAndResetRect.width = Mathf.Max(0f, controlAndResetRect.width - labelWidth); + SplitControlAndResetRect(controlAndResetRect, out controlRect, out resetRect, applyControlIndentCompensation); + } + + + protected static GUIContent LocalizedContent( + string tableName, + string labelKey, + string labelFallback, + string tooltipKey = null, + string tooltipFallback = "") + { + return ShaderGUILocalization.MakeContent(tableName, labelKey, labelFallback, tooltipKey, tooltipFallback); + } + + protected static GUIContent LocalizedInspectorContent(string tableName, string key, string fallback, string tip = "") + { + return ShaderGUILocalization.MakeInspectorContent(tableName, key, fallback, tip); + } + + protected static string LocalizedText(string tableName, string key, string fallback = "") + { + return ShaderGUILocalization.GetInspectorText(tableName, key, fallback); + } + + protected static string[] LocalizedOptions(string tableName, string key, string[] fallback) + { + return ShaderGUILocalization.GetInspectorOptions(tableName, key, fallback); + } + + public static void SplitControlAndResetRect( + Rect baseRect, + out Rect controlRect, + out Rect resetRect, + bool applyControlIndentCompensation = true) + { + resetRect = baseRect; + resetRect.x = baseRect.xMax - ResetButtonSize; + resetRect.width = ResetButtonSize; + + float controlIndentCompensation = applyControlIndentCompensation ? ControlIndentCompensation : 0f; + controlRect = baseRect; + controlRect.x -= controlIndentCompensation; + controlRect.width = Mathf.Max(0f, baseRect.width - ResetButtonSize - ControlResetGap + controlIndentCompensation); + } + + protected Rect LayoutRect(float height = -1f) + { + return RootItem.GetControlRect(height); + } + + protected void LayoutSpace(float height = -1f) + { + RootItem.Space(height); + } + + protected void DrawLayoutHelpBox(string message, MessageType messageType) + { + TempHelpContent.text = message; + float width = Mathf.Max(1f, EditorGUIUtility.currentViewWidth + GlobalRectWidthExpansion + GlobalRectXOffset); + float height = Mathf.Max( + EditorGUIUtility.singleLineHeight * 2f, + EditorStyles.helpBox.CalcHeight(TempHelpContent, width)); + Rect rect = ApplyGlobalRectCompensation(LayoutRect(height)); + EditorGUI.HelpBox(rect, message, messageType); + TempHelpContent.text = string.Empty; + } + + + public virtual void OnGUI() + { + GetRect(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + using (ParentControlDisabledScope()) + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = PropertyInfo.Property.hasMixedValue; + bool animatedPropertyScope = BeginAnimatedPropertyBackground(BaseRect, PropertyInfo.Property); + using (new EditorGUIIndentLevelScope(0)) + { + DrawController(); + } + EndAnimatedPropertyBackground(animatedPropertyScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + OnEndChange(); + } + } + + DrawResetButton(); + DrawBlock(); + } + + public void DrawResetButton()//如果重写OnGUI,一定要记得调用DrawResetButton + { + CheckIsPropertyModified(); + _resetButtonContent.text = HasModified ? "R" : ""; + _resetButtonStyle = HasModified ? GUI.skin.button : GUI.skin.label; + using (ParentControlDisabledScope()) + { + if (GUI.Button(ResetRect, _resetButtonContent, _resetButtonStyle)) + { + ExecuteReset(); + } + } + } + + public virtual void DrawController() + { + + } + + protected static bool SetFloatIfDifferent(MaterialProperty property, float value) + { + if (property == null || Mathf.Approximately(property.floatValue, value)) + { + return false; + } + + property.floatValue = value; + return true; + } + + protected static bool SetVectorIfDifferent(MaterialProperty property, Vector4 value) + { + if (property == null || Approximately(property.vectorValue, value)) + { + return false; + } + + property.vectorValue = value; + return true; + } + + protected static bool SetColorIfDifferent(MaterialProperty property, Color value) + { + if (property == null) + { + return false; + } + + Color current = property.colorValue; + if (Mathf.Approximately(current.r, value.r) && + Mathf.Approximately(current.g, value.g) && + Mathf.Approximately(current.b, value.b) && + Mathf.Approximately(current.a, value.a)) + { + return false; + } + + property.colorValue = value; + return true; + } + + protected readonly struct EditorGUIIndentLevelScope : System.IDisposable + { + private readonly int _indentLevel; + + public EditorGUIIndentLevelScope(int indentLevel) + { + _indentLevel = EditorGUI.indentLevel; + EditorGUI.indentLevel = indentLevel; + } + + public void Dispose() + { + EditorGUI.indentLevel = _indentLevel; + } + } + + protected bool IsParentControlDisabled => _parentControlDisabledDepth > 0; + + protected EditorGUI.DisabledScope ParentControlDisabledScope(bool disabled = false) + { + return new EditorGUI.DisabledScope(IsParentControlDisabled || disabled); + } + + protected readonly struct InheritedControlDisabledScope : System.IDisposable + { + private readonly bool _disabled; + + public InheritedControlDisabledScope(bool disabled) + { + _disabled = disabled; + if (_disabled) + { + _parentControlDisabledDepth++; + } + } + + public void Dispose() + { + if (_disabled) + { + _parentControlDisabledDepth = Mathf.Max(0, _parentControlDisabledDepth - 1); + } + } + } + + public virtual void DrawBlock() + { + + } + + public virtual void OnEndChange() + { + CheckIsPropertyModified(); + } + + private readonly Dictionary _animationPropertyPathDic = new Dictionary(); + + protected bool BeginAnimatedPropertyBackground(Rect totalPosition, MaterialProperty property) + { + if (property == null || RootItem?.MatEditor == null) + { + return false; + } + + RootItem.MatEditor.BeginAnimatedCheck(totalPosition, property); + return true; + } + + protected void EndAnimatedPropertyBackground(bool scopeActive) + { + if (scopeActive && RootItem?.MatEditor != null) + { + RootItem.MatEditor.EndAnimatedCheck(); + } + } + + public bool IsPropertyAnimated(string propertyName, params string[] componentNames) + { + if (propertyName == null) return false; + if (AnimationMode.InAnimationMode()) + { + foreach (var r in RootItem.RenderersUsingThisMaterial) + { + if (componentNames != null && componentNames.Length > 0) + { + foreach (string componentName in componentNames) + { + if (AnimationMode.IsPropertyAnimated(r, GetAnimationPropertyPath(propertyName, componentName))) + { + return true; + } + } + } + else if (AnimationMode.IsPropertyAnimated(r, GetAnimationPropertyPath(propertyName, string.Empty))) + { + return true; + } + } + } + + return false; + } + + private string GetAnimationPropertyPath(string propertyName, string componentName) + { + string key = string.IsNullOrEmpty(componentName) ? propertyName : propertyName + "." + componentName; + if (!_animationPropertyPathDic.TryGetValue(key, out string propertyPath)) + { + propertyPath = string.IsNullOrEmpty(componentName) + ? "material." + propertyName + : "material." + propertyName + "." + componentName; + _animationPropertyPathDic.Add(key, propertyPath); + } + + return propertyPath; + } + + + #region ResetLogic + + + private GUIContent _resetButtonContent = new GUIContent("R","重置当前属性及子集属性(如有)"); + private GUIStyle _resetButtonStyle; + public bool HasModified = false; + public bool PropertyIsDefaultValue = true; + public virtual void CheckIsPropertyModified(bool isCallByChild = false) + { + if (!isCallByChild)//只有自身Reset了,才需要查询自己的状态是否正确 + { + bool isDefaultValue = true; + if (PropertyInfo != null) + { + switch (ShaderGUIUnityCompat.GetPropertyType(PropertyInfo.Property)) + { + case ShaderPropertyType.Float: + case ShaderPropertyType.Range: + float defaultValue = RootItem.Shader.GetPropertyDefaultFloatValue(PropertyInfo.Index); + isDefaultValue = Mathf.Approximately(PropertyInfo.Property.floatValue, defaultValue); + break; + case ShaderPropertyType.Color: + Vector4 defaultColor = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + isDefaultValue = Approximately(PropertyInfo.Property.colorValue, defaultColor); + break; + case ShaderPropertyType.Vector: + Vector4 defaultVector = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + isDefaultValue = Approximately(PropertyInfo.Property.vectorValue, defaultVector); + break; + } + } + else + { + isDefaultValue = true;//如果没有Property,则是看子集的情况 + } + + if (isDefaultValue == PropertyIsDefaultValue) + { + return;//如果状态没有改变,就不需要做任何操作 + } + else + { + PropertyIsDefaultValue = isDefaultValue; + } + } + + HasModified = !PropertyIsDefaultValue; + + foreach (var childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + ParentItem?.CheckIsPropertyModified(true); + } + + public virtual void ExecuteReset(bool isCallByParent = false) + { + if (PropertyInfo != null) + { + switch (ShaderGUIUnityCompat.GetPropertyType(PropertyInfo.Property)) + { + case ShaderPropertyType.Float: + case ShaderPropertyType.Range: + float defaultValue = RootItem.Shader.GetPropertyDefaultFloatValue(PropertyInfo.Index); + PropertyInfo.Property.floatValue = defaultValue; + break; + case ShaderPropertyType.Color: + PropertyInfo.Property.colorValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + break; + case ShaderPropertyType.Vector: + PropertyInfo.Property.vectorValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + break; + } + PropertyIsDefaultValue = true; + } + + foreach (var childItem in ChildrenItemList) + { + childItem.ExecuteReset(true); + } + HasModified = false; + if (!isCallByParent)//直接由用户触发重置 + { + ParentItem?.CheckIsPropertyModified(true); + } + } + + protected static bool Approximately(Vector4 a, Vector4 b) + { + return Mathf.Approximately(a.x, b.x) && + Mathf.Approximately(a.y, b.y) && + Mathf.Approximately(a.z, b.z) && + Mathf.Approximately(a.w, b.w); + } + + #endregion + + + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIItem.cs.meta new file mode 100644 index 00000000..18b68bc7 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4f948e090bae4a558a52cb56d0b6c9fc +timeCreated: 1758127003 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUILocalization.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUILocalization.cs new file mode 100644 index 00000000..86a84c4e --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUILocalization.cs @@ -0,0 +1,894 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public static class ShaderGUILocalization + { + public const string DefaultLanguage = "zh-CN"; + public const string EnglishLanguage = "en-US"; + + private const string TooltipColumnSuffix = "-tip"; + private const string TooltipColumnAliasSuffix = "-tooltip"; + + private static readonly Dictionary Tables = + new Dictionary(StringComparer.OrdinalIgnoreCase); + private static NBFXLanguageMode s_CachedLanguageMode; + private static string s_CachedPreferredLanguage; + private static bool s_CachedPreferredLanguageValid; + + public static void RegisterCsv(string tableName, string csvAssetPath) + { + tableName = NormalizeTableName(tableName); + if (Tables.TryGetValue(tableName, out LocalizationTable table)) + { + if (string.Equals(table.CsvAssetPath, csvAssetPath, StringComparison.OrdinalIgnoreCase)) + { + return; + } + + table.CsvAssetPath = csvAssetPath; + table.Reload(); + return; + } + + Tables[tableName] = new LocalizationTable(csvAssetPath); + } + + public static string GetCurrentLanguage(string tableName) + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + return GetCurrentLanguage(table); + } + + public static string GetEditorLanguageName() + { + return GetLanguageFromEditor(); + } + + private static string GetCurrentLanguage(LocalizationTable table) + { + string preferred = GetPreferredLanguageName(); + foreach (string language in table.Languages) + { + if (string.Equals(language, preferred, StringComparison.OrdinalIgnoreCase)) + { + return language; + } + } + + return DefaultLanguage; + } + + public static GUIContent MakeContent( + string tableName, + string labelKey, + string labelFallback, + string tooltipKey = null, + string tooltipFallback = "") + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + string language = GetCurrentLanguage(table); + var cacheKey = new ContentCacheKey(language, labelKey, labelFallback, tooltipKey, tooltipFallback); + if (table.ContentCache.TryGetValue(cacheKey, out GUIContent cachedContent)) + { + return cachedContent; + } + + var content = new GUIContent( + GetLocalizedValue(table, labelKey, labelFallback, language), + GetTooltip(table, labelKey, tooltipKey, tooltipFallback, language)); + table.ContentCache[cacheKey] = content; + return content; + } + + public static GUIContent MakeInspectorContent(string tableName, string key, string fallback, string tip = "") + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + string language = GetCurrentLanguage(table); + var cacheKey = new InspectorContentCacheKey(language, key, fallback, tip); + if (table.InspectorContentCache.TryGetValue(cacheKey, out GUIContent cachedContent)) + { + return cachedContent; + } + + string labelKey = "inspector." + key + ".label"; + string tooltipKey = "inspector." + key + ".tip"; + var content = new GUIContent( + GetLocalizedValue(table, labelKey, fallback, language), + GetTooltip(table, labelKey, tooltipKey, tip, language)); + table.InspectorContentCache[cacheKey] = content; + return content; + } + + public static string GetInspectorText(string tableName, string key, string fallback = "") + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + string language = GetCurrentLanguage(table); + return GetInspectorText(table, key, fallback, language); + } + + public static string GetInspectorText(string tableName, string key, string fallback, string language) + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + return GetInspectorText(table, key, fallback, language); + } + + private static string GetInspectorText(LocalizationTable table, string key, string fallback, string language) + { + var cacheKey = new InspectorTextCacheKey(language, key, fallback); + if (table.InspectorTextCache.TryGetValue(cacheKey, out string cachedText)) + { + return cachedText; + } + + cachedText = GetLocalizedValue(table, "inspector." + key, fallback, language); + table.InspectorTextCache[cacheKey] = cachedText; + return cachedText; + } + + public static string[] GetInspectorOptions(string tableName, string key, string[] fallback) + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + string language = GetCurrentLanguage(table); + return GetInspectorOptions(table, key, fallback, language); + } + + public static string[] GetInspectorOptions(string tableName, string key, string[] fallback, string language) + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + return GetInspectorOptions(table, key, fallback, language); + } + + private static string[] GetInspectorOptions(LocalizationTable table, string key, string[] fallback, string language) + { + if (fallback == null) + { + return Array.Empty(); + } + + var cacheKey = new OptionsCacheKey(language, key, fallback); + if (table.InspectorOptionsCache.TryGetValue(cacheKey, out string[] cachedValues)) + { + return cachedValues; + } + + string keyPrefix = "inspector." + key + ".option"; + string[] values = new string[fallback.Length]; + for (int i = 0; i < fallback.Length; i++) + { + values[i] = GetLocalizedValue(table, keyPrefix + "." + i, fallback[i], language); + } + + table.InspectorOptionsCache[cacheKey] = values; + return values; + } + + public static string[] GetOptions(string tableName, string keyPrefix, string[] fallback) + { + if (fallback == null) + { + return Array.Empty(); + } + + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + string language = GetCurrentLanguage(table); + var cacheKey = new OptionsCacheKey(language, keyPrefix, fallback); + if (table.OptionsCache.TryGetValue(cacheKey, out string[] cachedValues)) + { + return cachedValues; + } + + string[] values = new string[fallback.Length]; + for (int i = 0; i < fallback.Length; i++) + { + values[i] = GetLocalizedValue(table, keyPrefix + "." + i, fallback[i], language); + } + + table.OptionsCache[cacheKey] = values; + return values; + } + + public static string Get(string tableName, string key, string fallback = "") + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + return GetLocalizedValue(table, key, fallback, GetCurrentLanguage(table)); + } + + private static string GetLocalizedValue(LocalizationTable table, string key, string fallback, string language) + { + if (string.IsNullOrEmpty(key)) + { + return fallback; + } + + if (table.Rows.TryGetValue(key, out Dictionary row)) + { + if (row.TryGetValue(language, out string localizedValue) && !string.IsNullOrEmpty(localizedValue)) + { + return localizedValue; + } + + if (row.TryGetValue(DefaultLanguage, out string defaultValue) && !string.IsNullOrEmpty(defaultValue)) + { + return defaultValue; + } + } + + return fallback; + } + + public static string GetTooltip(string tableName, string labelKey, string tooltipKey = null, string fallback = "") + { + LocalizationTable table = GetTable(tableName); + table.EnsureLoaded(); + return GetTooltip(table, labelKey, tooltipKey, fallback, GetCurrentLanguage(table)); + } + + private static string GetTooltip( + LocalizationTable table, + string labelKey, + string tooltipKey, + string fallback, + string language) + { + if (!string.IsNullOrEmpty(labelKey) && + table.Rows.TryGetValue(labelKey, out Dictionary row)) + { + if (TryGetTooltip(row, language, out string localizedTooltip)) + { + return localizedTooltip; + } + + if (TryGetTooltip(row, DefaultLanguage, out string defaultTooltip)) + { + return defaultTooltip; + } + } + + if (!string.IsNullOrEmpty(tooltipKey)) + { + return GetLocalizedValue(table, tooltipKey, fallback, language); + } + + return fallback; + } + + public static void Reload(string tableName = null) + { + if (string.IsNullOrEmpty(tableName)) + { + foreach (LocalizationTable table in Tables.Values) + { + table.Reload(); + } + + InvalidatePreferredLanguageCache(); + return; + } + + GetTable(tableName).Reload(); + InvalidatePreferredLanguageCache(); + } + + private static void InvalidatePreferredLanguageCache() + { + s_CachedPreferredLanguageValid = false; + } + + private static LocalizationTable GetTable(string tableName) + { + tableName = NormalizeTableName(tableName); + if (!Tables.TryGetValue(tableName, out LocalizationTable table)) + { + table = new LocalizationTable(string.Empty); + Tables[tableName] = table; + } + + return table; + } + + private static string NormalizeTableName(string tableName) + { + return string.IsNullOrEmpty(tableName) ? "default" : tableName; + } + + private static bool IsTooltipColumn(string header) + { + return !string.IsNullOrEmpty(header) && + (header.EndsWith(TooltipColumnSuffix, StringComparison.OrdinalIgnoreCase) || + header.EndsWith(TooltipColumnAliasSuffix, StringComparison.OrdinalIgnoreCase)); + } + + private static bool TryGetTooltip(Dictionary row, string language, out string tooltip) + { + tooltip = string.Empty; + if (string.IsNullOrEmpty(language)) + { + return false; + } + + if (row.TryGetValue(language + TooltipColumnSuffix, out tooltip) && !string.IsNullOrEmpty(tooltip)) + { + return true; + } + + if (row.TryGetValue(language + TooltipColumnAliasSuffix, out tooltip) && !string.IsNullOrEmpty(tooltip)) + { + return true; + } + + return false; + } + + private static string GetPreferredLanguageName() + { + NBFXLanguageMode languageMode = NBFXProjectSettings.LanguageMode; + if (s_CachedPreferredLanguageValid && s_CachedLanguageMode == languageMode) + { + return s_CachedPreferredLanguage; + } + + string language; + switch (languageMode) + { + case NBFXLanguageMode.Chinese: + language = DefaultLanguage; + break; + case NBFXLanguageMode.English: + language = EnglishLanguage; + break; + case NBFXLanguageMode.FollowEditor: + default: + language = GetLanguageFromEditor(); + break; + } + + s_CachedLanguageMode = languageMode; + s_CachedPreferredLanguage = language; + s_CachedPreferredLanguageValid = true; + return language; + } + + private static string GetLanguageFromEditor() + { + if (TryGetEditorLanguageName(out string language)) + { + return language; + } + + return GetSystemLanguageName(); + } + + private static bool TryGetEditorLanguageName(out string language) + { + language = string.Empty; + + Type localizationDatabaseType = typeof(Editor).Assembly.GetType("UnityEditor.LocalizationDatabase"); + if (localizationDatabaseType == null) + { + return false; + } + + const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; + string[] memberNames = + { + "currentEditorLanguage", + "CurrentEditorLanguage" + }; + + foreach (string memberName in memberNames) + { + PropertyInfo propertyInfo = localizationDatabaseType.GetProperty(memberName, flags); + if (propertyInfo != null && TryGetEditorLanguageValue(() => propertyInfo.GetValue(null, null), out language)) + { + return true; + } + + FieldInfo fieldInfo = localizationDatabaseType.GetField(memberName, flags); + if (fieldInfo != null && TryGetEditorLanguageValue(() => fieldInfo.GetValue(null), out language)) + { + return true; + } + } + + return false; + } + + private static bool TryGetEditorLanguageValue(Func valueGetter, out string language) + { + language = string.Empty; + try + { + return TryMapLanguageValue(valueGetter(), out language); + } + catch + { + return false; + } + } + + private static bool TryMapLanguageValue(object value, out string language) + { + language = string.Empty; + if (value == null) + { + return false; + } + + if (value is SystemLanguage systemLanguage) + { + language = MapSystemLanguage(systemLanguage); + return true; + } + + string languageName = value.ToString(); + if (string.IsNullOrEmpty(languageName)) + { + return false; + } + + string normalizedLanguageName = languageName.Replace("_", "-").ToLowerInvariant(); + if (normalizedLanguageName.StartsWith("en", StringComparison.Ordinal) || + normalizedLanguageName.Contains("english")) + { + language = EnglishLanguage; + return true; + } + + if (normalizedLanguageName.StartsWith("zh", StringComparison.Ordinal) || + normalizedLanguageName.Contains("chinese")) + { + language = DefaultLanguage; + return true; + } + + language = DefaultLanguage; + return true; + } + + private static string GetSystemLanguageName() + { + return MapSystemLanguage(Application.systemLanguage); + } + + private static string MapSystemLanguage(SystemLanguage systemLanguage) + { + switch (systemLanguage) + { + case SystemLanguage.English: + return EnglishLanguage; + case SystemLanguage.Chinese: + case SystemLanguage.ChineseSimplified: + case SystemLanguage.ChineseTraditional: + return DefaultLanguage; + default: + return DefaultLanguage; + } + } + + private readonly struct ContentCacheKey : IEquatable + { + private readonly string _language; + private readonly string _labelKey; + private readonly string _labelFallback; + private readonly string _tooltipKey; + private readonly string _tooltipFallback; + + public ContentCacheKey( + string language, + string labelKey, + string labelFallback, + string tooltipKey, + string tooltipFallback) + { + _language = language; + _labelKey = labelKey; + _labelFallback = labelFallback; + _tooltipKey = tooltipKey; + _tooltipFallback = tooltipFallback; + } + + public bool Equals(ContentCacheKey other) + { + return StringEquals(_language, other._language) && + StringEquals(_labelKey, other._labelKey) && + StringEquals(_labelFallback, other._labelFallback) && + StringEquals(_tooltipKey, other._tooltipKey) && + StringEquals(_tooltipFallback, other._tooltipFallback); + } + + public override bool Equals(object obj) + { + return obj is ContentCacheKey other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + hash = hash * 31 + StringHash(_language); + hash = hash * 31 + StringHash(_labelKey); + hash = hash * 31 + StringHash(_labelFallback); + hash = hash * 31 + StringHash(_tooltipKey); + hash = hash * 31 + StringHash(_tooltipFallback); + return hash; + } + } + } + + private readonly struct InspectorContentCacheKey : IEquatable + { + private readonly string _language; + private readonly string _key; + private readonly string _fallback; + private readonly string _tip; + + public InspectorContentCacheKey(string language, string key, string fallback, string tip) + { + _language = language; + _key = key; + _fallback = fallback; + _tip = tip; + } + + public bool Equals(InspectorContentCacheKey other) + { + return StringEquals(_language, other._language) && + StringEquals(_key, other._key) && + StringEquals(_fallback, other._fallback) && + StringEquals(_tip, other._tip); + } + + public override bool Equals(object obj) + { + return obj is InspectorContentCacheKey other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + hash = hash * 31 + StringHash(_language); + hash = hash * 31 + StringHash(_key); + hash = hash * 31 + StringHash(_fallback); + hash = hash * 31 + StringHash(_tip); + return hash; + } + } + } + + private readonly struct OptionsCacheKey : IEquatable + { + private readonly string _language; + private readonly string _keyPrefix; + private readonly string[] _fallback; + private readonly int _fallbackLength; + + public OptionsCacheKey(string language, string keyPrefix, string[] fallback) + { + _language = language; + _keyPrefix = keyPrefix; + _fallback = fallback; + _fallbackLength = fallback != null ? fallback.Length : 0; + } + + public bool Equals(OptionsCacheKey other) + { + if (!StringEquals(_language, other._language) || + !StringEquals(_keyPrefix, other._keyPrefix) || + _fallbackLength != other._fallbackLength) + { + return false; + } + + for (int i = 0; i < _fallbackLength; i++) + { + if (!StringEquals(_fallback[i], other._fallback[i])) + { + return false; + } + } + + return true; + } + + public override bool Equals(object obj) + { + return obj is OptionsCacheKey other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + hash = hash * 31 + StringHash(_language); + hash = hash * 31 + StringHash(_keyPrefix); + hash = hash * 31 + _fallbackLength; + for (int i = 0; i < _fallbackLength; i++) + { + hash = hash * 31 + StringHash(_fallback[i]); + } + + return hash; + } + } + } + + private readonly struct InspectorTextCacheKey : IEquatable + { + private readonly string _language; + private readonly string _key; + private readonly string _fallback; + + public InspectorTextCacheKey(string language, string key, string fallback) + { + _language = language; + _key = key; + _fallback = fallback; + } + + public bool Equals(InspectorTextCacheKey other) + { + return StringEquals(_language, other._language) && + StringEquals(_key, other._key) && + StringEquals(_fallback, other._fallback); + } + + public override bool Equals(object obj) + { + return obj is InspectorTextCacheKey other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + hash = hash * 31 + StringHash(_language); + hash = hash * 31 + StringHash(_key); + hash = hash * 31 + StringHash(_fallback); + return hash; + } + } + } + + private static bool StringEquals(string a, string b) + { + return string.Equals(a, b, StringComparison.Ordinal); + } + + private static int StringHash(string value) + { + return value == null ? 0 : StringComparer.Ordinal.GetHashCode(value); + } + + private sealed class LocalizationTable + { + private bool _loaded; + private bool _warningLogged; + + public LocalizationTable(string csvAssetPath) + { + CsvAssetPath = csvAssetPath; + Rows = new Dictionary>(StringComparer.OrdinalIgnoreCase); + Languages = Array.Empty(); + ContentCache = new Dictionary(); + InspectorContentCache = new Dictionary(); + InspectorTextCache = new Dictionary(); + OptionsCache = new Dictionary(); + InspectorOptionsCache = new Dictionary(); + } + + public string CsvAssetPath { get; set; } + public Dictionary> Rows { get; private set; } + public string[] Languages { get; private set; } + public Dictionary ContentCache { get; } + public Dictionary InspectorContentCache { get; } + public Dictionary InspectorTextCache { get; } + public Dictionary OptionsCache { get; } + public Dictionary InspectorOptionsCache { get; } + + public void Reload() + { + _loaded = false; + _warningLogged = false; + Rows = new Dictionary>(StringComparer.OrdinalIgnoreCase); + Languages = Array.Empty(); + ContentCache.Clear(); + InspectorContentCache.Clear(); + InspectorTextCache.Clear(); + OptionsCache.Clear(); + InspectorOptionsCache.Clear(); + } + + public void EnsureLoaded() + { + if (_loaded) + { + return; + } + + _loaded = true; + Rows = new Dictionary>(StringComparer.OrdinalIgnoreCase); + Languages = Array.Empty(); + + if (string.IsNullOrEmpty(CsvAssetPath)) + { + LogWarningOnce("ShaderGUI localization table is not registered."); + return; + } + + TextAsset csvAsset = AssetDatabase.LoadAssetAtPath(CsvAssetPath); + if (csvAsset == null) + { + LogWarningOnce($"ShaderGUI localization csv not found at '{CsvAssetPath}'."); + return; + } + + ParseCsv(csvAsset.text); + } + + private void ParseCsv(string csvText) + { + List rows = SplitRows(csvText); + if (rows.Count == 0) + { + return; + } + + List headers = ParseCsvRow(rows[0]); + if (headers.Count < 2) + { + return; + } + + var languages = new List(); + for (int i = 1; i < headers.Count; i++) + { + if (!IsTooltipColumn(headers[i])) + { + languages.Add(headers[i]); + } + } + + Languages = languages.ToArray(); + for (int rowIndex = 1; rowIndex < rows.Count; rowIndex++) + { + List values = ParseCsvRow(rows[rowIndex]); + if (values.Count == 0 || string.IsNullOrWhiteSpace(values[0])) + { + continue; + } + + var languageMap = new Dictionary(StringComparer.OrdinalIgnoreCase); + for (int i = 1; i < headers.Count; i++) + { + languageMap[headers[i]] = i < values.Count ? values[i] : string.Empty; + } + + Rows[values[0]] = languageMap; + } + } + + private static List SplitRows(string csvText) + { + var rows = new List(); + if (string.IsNullOrEmpty(csvText)) + { + return rows; + } + + var builder = new StringBuilder(); + bool inQuotes = false; + for (int i = 0; i < csvText.Length; i++) + { + char current = csvText[i]; + if (current == '"') + { + if (inQuotes && i + 1 < csvText.Length && csvText[i + 1] == '"') + { + builder.Append('"'); + i++; + } + else + { + inQuotes = !inQuotes; + } + + continue; + } + + if (!inQuotes && (current == '\n' || current == '\r')) + { + if (builder.Length > 0) + { + rows.Add(builder.ToString()); + builder.Length = 0; + } + + if (current == '\r' && i + 1 < csvText.Length && csvText[i + 1] == '\n') + { + i++; + } + + continue; + } + + builder.Append(current); + } + + if (builder.Length > 0) + { + rows.Add(builder.ToString()); + } + + return rows; + } + + private static List ParseCsvRow(string rowText) + { + var values = new List(); + var builder = new StringBuilder(); + bool inQuotes = false; + for (int i = 0; i < rowText.Length; i++) + { + char current = rowText[i]; + if (current == '"') + { + if (inQuotes && i + 1 < rowText.Length && rowText[i + 1] == '"') + { + builder.Append('"'); + i++; + } + else + { + inQuotes = !inQuotes; + } + + continue; + } + + if (!inQuotes && current == ',') + { + values.Add(builder.ToString()); + builder.Length = 0; + continue; + } + + builder.Append(current); + } + + values.Add(builder.ToString()); + return values; + } + + private void LogWarningOnce(string message) + { + if (_warningLogged) + { + return; + } + + _warningLogged = true; + Debug.LogWarning(message); + } + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUILocalization.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUILocalization.cs.meta new file mode 100644 index 00000000..815fd7d5 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUILocalization.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a5429c73ee5e4590bbbbccee3d5a3a58 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIPopUpItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIPopUpItem.cs new file mode 100644 index 00000000..092e1ced --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIPopUpItem.cs @@ -0,0 +1,158 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class ShaderGUIPopUpItem:ShaderGUIItem + { + private readonly Func _contentProvider; + private readonly Func _popupNamesProvider; + private readonly Action _onValueChanged; + private readonly Func _isVisible; + + public ShaderGUIPopUpItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : + base(rootItem, parentItem: parentItem) + { + // base.InitTriggerByChild(); + } + + public ShaderGUIPopUpItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + Func contentProvider, + Func popupNamesProvider, + Action onValueChanged = null, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _popupNamesProvider = popupNamesProvider; + _onValueChanged = onValueChanged; + _isVisible = isVisible; + GuiContent = _contentProvider(); + PopUpNames = _popupNamesProvider?.Invoke(); + InitTriggerByChild(); + } + + public string[] PopUpNames; + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + base.OnGUI(); + } + + public override void DrawController() + { + int value = EditorGUI.Popup(ControlRect, (int)PropertyInfo.Property.floatValue, PopUpNames); + SetFloatIfDifferent(PropertyInfo.Property, value); + } + + public override void OnEndChange() + { + base.OnEndChange(); + _onValueChanged?.Invoke(PropertyInfo.Property); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + base.ExecuteReset(isCallByParent); + OnEndChange(); + } + } + + public class ShaderGUIBitMaskItem : ShaderGUIItem + { + private static readonly string[] EmptyMaskNames = new string[0]; + + private readonly Func _contentProvider; + private readonly Func _maskNamesProvider; + private readonly Action _onValueChanged; + private readonly Func _isVisible; + + public ShaderGUIBitMaskItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) + : base(rootItem, parentItem: parentItem) + { + } + + public ShaderGUIBitMaskItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + Func contentProvider, + Func maskNamesProvider, + Action onValueChanged = null, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _maskNamesProvider = maskNamesProvider; + _onValueChanged = onValueChanged; + _isVisible = isVisible; + GuiContent = _contentProvider(); + MaskNames = _maskNamesProvider?.Invoke(); + InitTriggerByChild(); + } + + public string[] MaskNames; + public int ValidMask = -1; + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + if (_contentProvider != null) + { + GuiContent = _contentProvider(); + } + + if (_maskNamesProvider != null) + { + MaskNames = _maskNamesProvider(); + } + + base.OnGUI(); + } + + public override void DrawController() + { + string[] maskNames = MaskNames ?? EmptyMaskNames; + int validMask = GetValidMask(maskNames); + int mask = Mathf.RoundToInt(PropertyInfo.Property.floatValue) & validMask; + int value = EditorGUI.MaskField(ControlRect, mask, maskNames) & validMask; + SetFloatIfDifferent(PropertyInfo.Property, value); + } + + public override void OnEndChange() + { + base.OnEndChange(); + _onValueChanged?.Invoke(PropertyInfo.Property); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + base.ExecuteReset(isCallByParent); + OnEndChange(); + } + + private int GetValidMask(string[] maskNames) + { + if (ValidMask >= 0) + { + return ValidMask; + } + + int optionCount = Mathf.Clamp(maskNames.Length, 0, 30); + return optionCount == 0 ? 0 : (1 << optionCount) - 1; + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIPopUpItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIPopUpItem.cs.meta new file mode 100644 index 00000000..ef729261 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIPopUpItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a4147e85b43d4bcaab43dedf111c41fb +timeCreated: 1758444036 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIRootItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIRootItem.cs new file mode 100644 index 00000000..25cccc13 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIRootItem.cs @@ -0,0 +1,288 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using NBShader; + +namespace NBShaderEditor +{ + public class ShaderPropertyInfo + { + public MaterialProperty Property; + public string Name; + public int Index; + } + public class ShaderGUIRootItem + { + private static int s_RendererCacheVersion; + private static double s_RendererCacheFirstDirtyTime = -1d; + private static double s_RendererCacheDirtyTime; + private const double RendererCacheHierarchyRefreshDelay = 0.35d; + private const double RendererCacheMaxHierarchyRefreshDelay = 2d; + private const float DefaultManualLayoutHeight = 1200f; + + public Shader Shader; + public MaterialEditor MatEditor; + public List Mats; + public Dictionary PropertyInfoDic = new Dictionary(); + public List ShaderFlags;//各个继承类各自初始化 + public bool IsInit = true; + public Color DefaultBackgroundColor; + public bool ClearUnusedTextureReferencesRequested { get; private set; } + public List RenderersUsingThisMaterial = new List(); + public List ParticleRenderersUsingThisMaterial = new List(); + public bool IsUsedByParticleSystem { get; private set; } + private int _rendererCacheVersion = -1; + private Material _rendererCacheMaterial; + private readonly List _rendererMaterialBuffer = new List(); + private bool _manualLayoutActive; + private Rect _manualLayoutRect; + private float _manualLayoutY; + private float _manualLayoutUsedHeight; + private float _manualLayoutHeight = DefaultManualLayoutHeight; + + static ShaderGUIRootItem() + { + EditorApplication.hierarchyChanged += OnHierarchyChanged; + } + + private static void OnHierarchyChanged() + { + double now = EditorApplication.timeSinceStartup; + s_RendererCacheVersion++; + if (s_RendererCacheFirstDirtyTime < 0d) + { + s_RendererCacheFirstDirtyTime = now; + } + + s_RendererCacheDirtyTime = now; + } + + public virtual void OnGUI(MaterialEditor editor,MaterialProperty[] props) + { + MatEditor = editor; + DefaultBackgroundColor = GUI.backgroundColor; + if (IsInit || ShouldRebuildMaterialTargets(editor.targets)) + { + IsInit = true; + Mats = new List(); + foreach (var obj in editor.targets) + { + Mats.Add(obj as Material); + } + InitFlags(Mats); + Shader = Mats[0].shader; + RefreshRendererCacheIfNeeded(true); + } + else + { + RefreshRendererCacheIfNeeded(false); + } + if (ShouldRebuildPropertyInfo(props)) + { + PropertyInfoDic.Clear(); + for (int i = 0; i < props.Length; i++) + { + ShaderPropertyInfo propInfo = new ShaderPropertyInfo(); + propInfo.Property = props[i]; + propInfo.Name = props[i].name; + propInfo.Index = i; + PropertyInfoDic.Add(propInfo.Name, propInfo); + } + } + else + { + for (int i = 0; i < props.Length; i++) + { + ShaderPropertyInfo propInfo = PropertyInfoDic[props[i].name]; + propInfo.Property = props[i]; + propInfo.Index = i; + } + } + + try + { + BeginManualLayout(); + OnChildOnGUI(); + } + finally + { + EndManualLayout(); + ClearUnusedTextureReferencesRequested = false; + } + + RepaintWhenAnimationModeActive(); + IsInit = false; + } + + public void RequestClearUnusedTextureReferences() + { + ClearUnusedTextureReferencesRequested = true; + } + + public Rect GetControlRect(float height = -1f) + { + float rectHeight = height >= 0f ? height : EditorGUIUtility.singleLineHeight; + if (!_manualLayoutActive) + { + return EditorGUILayout.GetControlRect(false, rectHeight); + } + + Rect rect = new Rect(_manualLayoutRect.x, _manualLayoutY, _manualLayoutRect.width, rectHeight); + _manualLayoutY += rectHeight + EditorGUIUtility.standardVerticalSpacing; + _manualLayoutUsedHeight = Mathf.Max( + _manualLayoutUsedHeight, + _manualLayoutY - _manualLayoutRect.y - EditorGUIUtility.standardVerticalSpacing); + return rect; + } + + public void Space(float height = -1f) + { + float spaceHeight = height >= 0f ? height : EditorGUIUtility.standardVerticalSpacing; + if (!_manualLayoutActive) + { + EditorGUILayout.Space(); + return; + } + + _manualLayoutY += spaceHeight; + _manualLayoutUsedHeight = Mathf.Max(_manualLayoutUsedHeight, _manualLayoutY - _manualLayoutRect.y); + } + + private void BeginManualLayout() + { + float height = Mathf.Max(EditorGUIUtility.singleLineHeight, _manualLayoutHeight); + _manualLayoutRect = EditorGUILayout.GetControlRect(false, height); + _manualLayoutY = _manualLayoutRect.y; + _manualLayoutUsedHeight = 0f; + _manualLayoutActive = true; + } + + private void EndManualLayout() + { + if (!_manualLayoutActive) + { + return; + } + + _manualLayoutActive = false; + float usedHeight = Mathf.Max(EditorGUIUtility.singleLineHeight, _manualLayoutUsedHeight); + if (!Mathf.Approximately(_manualLayoutHeight, usedHeight)) + { + _manualLayoutHeight = usedHeight; + MatEditor?.Repaint(); + } + } + + private bool ShouldRebuildPropertyInfo(MaterialProperty[] props) + { + if (PropertyInfoDic.Count != props.Length) + { + return true; + } + + for (int i = 0; i < props.Length; i++) + { + if (!PropertyInfoDic.ContainsKey(props[i].name)) + { + return true; + } + } + + return false; + } + + void RepaintWhenAnimationModeActive() + { + if (AnimationMode.InAnimationMode()) + { + MatEditor.Repaint(); + } + } + + private bool ShouldRebuildMaterialTargets(UnityEngine.Object[] targets) + { + if (Mats == null || targets == null || Mats.Count != targets.Length) + { + return true; + } + + for (int i = 0; i < targets.Length; i++) + { + if (Mats[i] != (targets[i] as Material)) + { + return true; + } + } + + return false; + } + + private void RefreshRendererCacheIfNeeded(bool force) + { + Material material = Mats != null && Mats.Count > 0 ? Mats[0] : null; + if (!force && _rendererCacheMaterial == material && _rendererCacheVersion == s_RendererCacheVersion) + { + return; + } + + double now = EditorApplication.timeSinceStartup; + bool waitingForQuietHierarchy = now - s_RendererCacheDirtyTime < RendererCacheHierarchyRefreshDelay; + bool withinMaxDelay = s_RendererCacheFirstDirtyTime >= 0d && + now - s_RendererCacheFirstDirtyTime < RendererCacheMaxHierarchyRefreshDelay; + if (!force && + _rendererCacheMaterial == material && + waitingForQuietHierarchy && + withinMaxDelay) + { + return; + } + + CacheRenderersUsingThisMaterial(material); + _rendererCacheMaterial = material; + _rendererCacheVersion = s_RendererCacheVersion; + s_RendererCacheFirstDirtyTime = -1d; + } + + void CacheRenderersUsingThisMaterial(Material material) + { + Renderer[] renderers = UnityObjectFindCompat.FindAll(); + RenderersUsingThisMaterial.Clear(); + ParticleRenderersUsingThisMaterial.Clear(); + IsUsedByParticleSystem = false; + if (material == null || renderers == null) + { + return; + } + + foreach (Renderer renderer in renderers) + { + if (renderer is ParticleSystemRenderer psr && + (psr.sharedMaterial == material || psr.trailMaterial == material)) + { + IsUsedByParticleSystem = true; + ParticleRenderersUsingThisMaterial.Add(psr); + } + + _rendererMaterialBuffer.Clear(); + renderer.GetSharedMaterials(_rendererMaterialBuffer); + for (int i = 0; i < _rendererMaterialBuffer.Count; i++) + { + if (_rendererMaterialBuffer[i] == material) + { + RenderersUsingThisMaterial.Add(renderer); + break; + } + } + } + + _rendererMaterialBuffer.Clear(); + } + + public virtual void InitFlags(List mats) { } //各个子类各自实现 + + public virtual void OnChildOnGUI() + { + + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIRootItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIRootItem.cs.meta new file mode 100644 index 00000000..f0962ecb --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ShaderGUIRootItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e57b381204754ae780ab305e5feff475 +timeCreated: 1758206205 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/TextureItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/TextureItem.cs new file mode 100644 index 00000000..667f908b --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/TextureItem.cs @@ -0,0 +1,498 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class TextureItem : ShaderGUIItem + { + private readonly string _texturePropertyName; + private readonly TexturePropertyGroupItem _groupItem; + private readonly Func _isVisible; + private readonly Action _afterDraw; + + public TextureItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string texturePropertyName, + Func contentProvider, + string colorPropertyName = null, + bool drawScaleOffset = true, + Action afterDraw = null, + Func isVisible = null, + Func tillingContentProvider = null, + Func offsetContentProvider = null) : base(rootItem, parentItem) + { + _texturePropertyName = texturePropertyName; + _isVisible = isVisible; + _afterDraw = afterDraw; + _groupItem = new TexturePropertyGroupItem( + rootItem, + this, + texturePropertyName, + colorPropertyName, + contentProvider, + drawScaleOffset, + tillingContentProvider: tillingContentProvider, + offsetContentProvider: offsetContentProvider); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + _groupItem.ClearTextureIfRequested(); + return; + } + + _groupItem.OnGUI(); + if (_afterDraw != null && RootItem.PropertyInfoDic.TryGetValue(_texturePropertyName, out ShaderPropertyInfo texturePropertyInfo)) + { + _afterDraw(texturePropertyInfo.Property); + } + } + } + + public class TexturePropertyGroupItem : ShaderGUIItem + { + private readonly TextureObjectItem _textureItem; + private readonly ColorLineItem _colorItem; + private readonly TextureScaleOffsetItem _scaleOffsetItem; + private readonly Func _isVisible; + + public TexturePropertyGroupItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string texturePropertyName, + string colorPropertyName, + Func contentProvider, + bool drawScaleOffset = true, + Func isVisible = null, + Func tillingContentProvider = null, + Func offsetContentProvider = null) : base(rootItem, parentItem) + { + _isVisible = isVisible; + _textureItem = new TextureObjectItem(rootItem, this, texturePropertyName, contentProvider); + _colorItem = string.IsNullOrEmpty(colorPropertyName) + ? null + : new ColorLineItem(rootItem, this, colorPropertyName, false, contentProvider); + _scaleOffsetItem = drawScaleOffset + ? new TextureScaleOffsetItem( + rootItem, + this, + texturePropertyName, + false, + tillingContentProvider: tillingContentProvider, + offsetContentProvider: offsetContentProvider) + : null; + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + _textureItem.ClearTextureIfRequested(); + return; + } + + float singleLineHeight = EditorGUIUtility.singleLineHeight; + float rowGap = EditorGUIUtility.standardVerticalSpacing; + float textureFieldHeight = 3f * singleLineHeight + 2f * rowGap; + float textureContentGap = EditorGUIUtility.standardVerticalSpacing; + + Rect textureGroupRect = ApplyGlobalRectCompensation(LayoutRect(textureFieldHeight)); + Rect textureLabelRow = new Rect(textureGroupRect.x, textureGroupRect.y, textureGroupRect.width, singleLineHeight); + Rect tillingRow = new Rect(textureGroupRect.x, textureGroupRect.y + singleLineHeight + rowGap, textureGroupRect.width, singleLineHeight); + Rect offsetRow = new Rect(textureGroupRect.x, tillingRow.y + singleLineHeight + rowGap, textureGroupRect.width, singleLineHeight); + Rect indentedTextureLabelRow = ApplyDirectLabelIndentWidth(textureLabelRow); + + Rect textureRect = new Rect(indentedTextureLabelRow.x + 2f, textureLabelRow.y, textureFieldHeight, textureFieldHeight); + textureRect.x -= 2f; + textureRect.y += 2f; + + float contentX = textureRect.x + textureRect.width + textureContentGap; + Rect textureLabelRect = MoveRectLeftKeepingRight(textureLabelRow, contentX); + + SplitLineRect(tillingRow, out _, out Rect tillingVec2Rect, out Rect tillingResetRect, false); + Rect tillingLabelRect = MakeLabelRect(tillingRow, contentX, tillingVec2Rect.x); + tillingVec2Rect = ApplyControlIndentCompensation(tillingVec2Rect); + + SplitLineRect(offsetRow, out _, out Rect offsetVec2Rect, out Rect offsetResetRect, false); + Rect offsetLabelRect = MakeLabelRect(offsetRow, contentX, offsetVec2Rect.x); + offsetVec2Rect = ApplyControlIndentCompensation(offsetVec2Rect); + + _textureItem.Draw(textureRect, textureLabelRect); + _scaleOffsetItem?.Draw(tillingLabelRect, tillingVec2Rect, tillingResetRect, offsetLabelRect, offsetVec2Rect, offsetResetRect); + _colorItem?.OnGUI(); + } + + public void ClearTextureIfRequested() + { + _textureItem.ClearTextureIfRequested(); + } + + private static Rect MoveRectLeftKeepingRight(Rect rect, float x) + { + float xMax = rect.xMax; + rect.x = Mathf.Min(x, xMax); + rect.width = xMax - rect.x; + return rect; + } + + private static Rect MakeLabelRect(Rect rowRect, float labelX, float controlX) + { + Rect labelRect = rowRect; + labelRect.x = Mathf.Min(labelX, controlX); + labelRect.width = Mathf.Max(0f, controlX - labelRect.x); + return labelRect; + } + + private static Rect ApplyControlIndentCompensation(Rect rect) + { + rect.x -= ControlIndentCompensation; + rect.width += ControlIndentCompensation; + return rect; + } + } + + public class TextureObjectItem : ShaderGUIItem + { + private readonly Func _contentProvider; + private readonly Func _isVisible; + + public TextureObjectItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string texturePropertyName, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = texturePropertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + ClearTextureIfRequested(); + return; + } + + GetRect(); + Draw(ControlRect, LabelRect, ResetRect); + DrawBlock(); + } + + public void Draw(Rect textureRect, Rect labelAndResetRect) + { + SplitControlAndResetRect(labelAndResetRect, out Rect labelRect, out Rect resetRect, false); + Draw(textureRect, labelRect, resetRect); + } + + public void Draw(Rect textureRect, Rect labelRect, Rect resetRect) + { + ControlRect = textureRect; + LabelRect = labelRect; + ResetRect = resetRect; + + MaterialProperty property = PropertyInfo.Property; + if (RootItem.ClearUnusedTextureReferencesRequested && (IsParentControlDisabled || !GUI.enabled)) + { + ClearTextureIfRequested(); + } + + using (ParentControlDisabledScope()) + { + GUI.Label(LabelRect, GuiContent, EditorStyles.boldLabel); + } + + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + bool animatedScope = BeginAnimatedPropertyBackground(ControlRect, property); + Texture texture; + using (new EditorGUIIndentLevelScope(0)) + { + texture = (Texture)EditorGUI.ObjectField(ControlRect, property.textureValue, typeof(Texture2D), false); + } + EndAnimatedPropertyBackground(animatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + property.textureValue = texture; + OnEndChange(); + } + } + + DrawResetButton(); + } + + public void ClearTextureIfRequested() + { + if (!RootItem.ClearUnusedTextureReferencesRequested || PropertyInfo == null) + { + return; + } + + MaterialProperty property = PropertyInfo.Property; + if (property == null || property.textureValue == null) + { + return; + } + + property.textureValue = null; + OnEndChange(); + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + if (!isCallByChild) + { + bool isDefaultValue = PropertyInfo == null || + (!PropertyInfo.Property.hasMixedValue && PropertyInfo.Property.textureValue == null); + if (isDefaultValue == PropertyIsDefaultValue) + { + return; + } + + PropertyIsDefaultValue = isDefaultValue; + } + + HasModified = !PropertyIsDefaultValue; + foreach (ShaderGUIItem childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + if (PropertyInfo != null) + { + PropertyInfo.Property.textureValue = null; + PropertyIsDefaultValue = true; + } + + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + } + + public class TextureScaleOffsetItem : ShaderGUIItem + { + private static readonly GUIContent TillingContent = new GUIContent("Tilling"); + private static readonly GUIContent OffsetContent = new GUIContent("Offset"); + private static readonly Vector4 DefaultScaleOffset = new Vector4(1f, 1f, 0f, 0f); + + private readonly bool _isVectorProperty; + private readonly Func _isVisible; + private readonly Func _tillingContentProvider; + private readonly Func _offsetContentProvider; + private readonly GUIContent _tillingContent; + private readonly GUIContent _offsetContent; + + public TextureScaleOffsetItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + bool isVectorProperty, + Func isVisible = null, + Func tillingContentProvider = null, + Func offsetContentProvider = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _isVectorProperty = isVectorProperty; + _isVisible = isVisible; + _tillingContentProvider = tillingContentProvider ?? (() => TillingContent); + _offsetContentProvider = offsetContentProvider ?? (() => OffsetContent); + _tillingContent = _tillingContentProvider(); + _offsetContent = _offsetContentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + Rect tillingLabelRect = LabelRect; + Rect tillingVec2Rect = ControlRect; + Rect tillingResetRect = ResetRect; + + GetRect(); + Rect offsetLabelRect = LabelRect; + Rect offsetVec2Rect = ControlRect; + Rect offsetResetRect = ResetRect; + + Draw(tillingLabelRect, tillingVec2Rect, tillingResetRect, offsetLabelRect, offsetVec2Rect, offsetResetRect, true); + DrawBlock(); + } + + public void Draw( + Rect tillingLabelRect, + Rect tillingVec2Rect, + Rect tillingResetRect, + Rect offsetLabelRect, + Rect offsetVec2Rect, + Rect offsetResetRect, + bool useEditorLabelField = false) + { + MaterialProperty property = PropertyInfo.Property; + Vector4 scaleOffset = GetScaleOffset(property); + + DrawLabel(tillingLabelRect, _tillingContent, useEditorLabelField); + using (ParentControlDisabledScope()) + { + Vector2 tilling = new Vector2(scaleOffset.x, scaleOffset.y); + EditorGUI.showMixedValue = property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + bool tillingAnimatedScope = BeginAnimatedPropertyBackground(tillingVec2Rect, property); + using (new EditorGUIIndentLevelScope(0)) + { + tilling = EditorGUI.Vector2Field(tillingVec2Rect, GUIContent.none, tilling); + } + EndAnimatedPropertyBackground(tillingAnimatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + scaleOffset.x = tilling.x; + scaleOffset.y = tilling.y; + Apply(scaleOffset); + } + + bool tillingModified = property.hasMixedValue || tilling != Vector2.one; + if (GUI.Button(tillingResetRect, tillingModified ? "R" : string.Empty, tillingModified ? GUI.skin.button : GUI.skin.label)) + { + scaleOffset.x = 1f; + scaleOffset.y = 1f; + Apply(scaleOffset); + } + } + + DrawLabel(offsetLabelRect, _offsetContent, useEditorLabelField); + using (ParentControlDisabledScope()) + { + Vector2 offset = new Vector2(scaleOffset.z, scaleOffset.w); + EditorGUI.showMixedValue = property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + bool offsetAnimatedScope = BeginAnimatedPropertyBackground(offsetVec2Rect, property); + using (new EditorGUIIndentLevelScope(0)) + { + offset = EditorGUI.Vector2Field(offsetVec2Rect, GUIContent.none, offset); + } + EndAnimatedPropertyBackground(offsetAnimatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + scaleOffset.z = offset.x; + scaleOffset.w = offset.y; + Apply(scaleOffset); + } + + bool offsetModified = property.hasMixedValue || offset != Vector2.zero; + if (GUI.Button(offsetResetRect, offsetModified ? "R" : string.Empty, offsetModified ? GUI.skin.button : GUI.skin.label)) + { + scaleOffset.z = 0f; + scaleOffset.w = 0f; + Apply(scaleOffset); + } + } + } + + private void DrawLabel(Rect rect, GUIContent content, bool useEditorLabelField) + { + using (ParentControlDisabledScope()) + { + if (useEditorLabelField) + { + EditorGUI.LabelField(rect, content); + return; + } + + GUI.Label(rect, content); + } + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + if (!isCallByChild) + { + bool isDefaultValue = true; + if (PropertyInfo != null) + { + MaterialProperty property = PropertyInfo.Property; + isDefaultValue = !property.hasMixedValue && Approximately(GetScaleOffset(property), DefaultScaleOffset); + } + + if (isDefaultValue == PropertyIsDefaultValue) + { + return; + } + + PropertyIsDefaultValue = isDefaultValue; + } + + HasModified = !PropertyIsDefaultValue; + foreach (ShaderGUIItem childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + if (PropertyInfo != null) + { + SetScaleOffset(PropertyInfo.Property, DefaultScaleOffset); + PropertyIsDefaultValue = true; + } + + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + + private Vector4 GetScaleOffset(MaterialProperty property) + { + return _isVectorProperty ? property.vectorValue : property.textureScaleAndOffset; + } + + private void Apply(Vector4 scaleOffset) + { + SetScaleOffset(PropertyInfo.Property, scaleOffset); + OnEndChange(); + } + + private void SetScaleOffset(MaterialProperty property, Vector4 scaleOffset) + { + if (_isVectorProperty) + { + property.vectorValue = scaleOffset; + } + else + { + property.textureScaleAndOffset = scaleOffset; + } + } + + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/TextureItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/TextureItem.cs.meta new file mode 100644 index 00000000..d5ac11d8 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/TextureItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7f026fa752b843a0b469f9306b2ff461 +timeCreated: 1777032000 diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ToggleItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ToggleItem.cs new file mode 100644 index 00000000..5c88babb --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ToggleItem.cs @@ -0,0 +1,58 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class ToggleItem : ShaderGUIItem + { + private readonly Func _contentProvider; + private readonly Func _isVisible; + private readonly Action _onValueChanged; + + public ToggleItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + Func contentProvider, + Action onValueChanged = null, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _onValueChanged = onValueChanged; + _isVisible = isVisible; + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + base.OnGUI(); + } + + public override void DrawController() + { + bool value = PropertyInfo.Property.floatValue > 0.5f; + value = EditorGUI.Toggle(ControlRect, value); + SetFloatIfDifferent(PropertyInfo.Property, value ? 1f : 0f); + } + + public override void OnEndChange() + { + base.OnEndChange(); + _onValueChanged?.Invoke(PropertyInfo.Property.floatValue > 0.5f); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + base.ExecuteReset(isCallByParent); + _onValueChanged?.Invoke(PropertyInfo.Property.floatValue > 0.5f); + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ToggleItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ToggleItem.cs.meta new file mode 100644 index 00000000..5d89c6d3 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/ToggleItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: afba064c4c70401bbb7133de835d2d35 +timeCreated: 1777032000 diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/VectorItem.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/VectorItem.cs new file mode 100644 index 00000000..c9229b6b --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/VectorItem.cs @@ -0,0 +1,610 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace NBShaderEditor +{ + public class Vector2LineItem : ShaderGUIItem + { + private readonly bool _firstLine; + private readonly Func _contentProvider; + private readonly Func _isVisible; + + public Vector2LineItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + bool firstLine, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _firstLine = firstLine; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + MaterialProperty property = PropertyInfo.Property; + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + Vector4 vector = property.vectorValue; + Vector2 value = _firstLine ? new Vector2(vector.x, vector.y) : new Vector2(vector.z, vector.w); + bool animatedScope = BeginAnimatedPropertyBackground(ControlRect, property); + using (new EditorGUIIndentLevelScope(0)) + { + value = EditorGUI.Vector2Field(ControlRect, GUIContent.none, value); + } + EndAnimatedPropertyBackground(animatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + if (_firstLine) + { + vector.x = value.x; + vector.y = value.y; + } + else + { + vector.z = value.x; + vector.w = value.y; + } + + property.vectorValue = vector; + OnEndChange(); + } + } + + DrawResetButton(); + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + if (PropertyInfo == null) + { + base.CheckIsPropertyModified(isCallByChild); + return; + } + + if (!isCallByChild) + { + Vector4 defaultValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + Vector4 currentValue = PropertyInfo.Property.vectorValue; + bool isDefaultValue = _firstLine + ? Mathf.Approximately(currentValue.x, defaultValue.x) && Mathf.Approximately(currentValue.y, defaultValue.y) + : Mathf.Approximately(currentValue.z, defaultValue.z) && Mathf.Approximately(currentValue.w, defaultValue.w); + + if (isDefaultValue == PropertyIsDefaultValue) + { + return; + } + + PropertyIsDefaultValue = isDefaultValue; + } + + HasModified = !PropertyIsDefaultValue; + foreach (var childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + Vector4 defaultValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + Vector4 currentValue = PropertyInfo.Property.vectorValue; + if (_firstLine) + { + currentValue.x = defaultValue.x; + currentValue.y = defaultValue.y; + } + else + { + currentValue.z = defaultValue.z; + currentValue.w = defaultValue.w; + } + + PropertyInfo.Property.vectorValue = currentValue; + PropertyIsDefaultValue = true; + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + } + + public class VectorComponentItem : ShaderGUIItem + { + private readonly int _componentIndex; + private readonly bool _isSlider; + private readonly float _min; + private readonly float _max; + private readonly Func _contentProvider; + private readonly Func _isVisible; + + public VectorComponentItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + int componentIndex, + Func contentProvider, + bool isSlider, + float min = 0f, + float max = 1f, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _componentIndex = componentIndex; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isSlider = isSlider; + _min = min; + _max = max; + _isVisible = isVisible; + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + MaterialProperty property = PropertyInfo.Property; + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + Vector4 vector = property.vectorValue; + float value = GetValue(vector); + value = _isSlider + ? DraggableLabelFloat.Handle( + LabelRect, + value, + DraggableLabelFloat.GetSensitivityByRange(_min, _max), + _min, + _max) + : DraggableLabelFloat.Handle(LabelRect, value); + if (_isSlider) + { + bool animatedScope = BeginAnimatedPropertyBackground(ControlRect, property); + using (new EditorGUIIndentLevelScope(0)) + { + value = EditorGUI.Slider(ControlRect, value, _min, _max); + } + EndAnimatedPropertyBackground(animatedScope); + } + else + { + bool animatedScope = BeginAnimatedPropertyBackground(ControlRect, property); + using (new EditorGUIIndentLevelScope(0)) + { + value = EditorGUI.FloatField(ControlRect, value); + } + EndAnimatedPropertyBackground(animatedScope); + } + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + SetValue(ref vector, value); + property.vectorValue = vector; + OnEndChange(); + } + } + + DrawResetButton(); + } + + private float GetValue(Vector4 vector) + { + switch (_componentIndex) + { + case 0: return vector.x; + case 1: return vector.y; + case 2: return vector.z; + case 3: return vector.w; + default: return vector.x; + } + } + + private void SetValue(ref Vector4 vector, float value) + { + switch (_componentIndex) + { + case 0: + vector.x = value; + break; + case 1: + vector.y = value; + break; + case 2: + vector.z = value; + break; + case 3: + vector.w = value; + break; + } + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + if (PropertyInfo == null) + { + base.CheckIsPropertyModified(isCallByChild); + return; + } + + if (!isCallByChild) + { + Vector4 defaultValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + bool isDefaultValue = Mathf.Approximately(GetValue(PropertyInfo.Property.vectorValue), GetValue(defaultValue)); + if (isDefaultValue == PropertyIsDefaultValue) + { + return; + } + + PropertyIsDefaultValue = isDefaultValue; + } + + HasModified = !PropertyIsDefaultValue; + foreach (var childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + Vector4 vector = PropertyInfo.Property.vectorValue; + Vector4 defaultValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + SetValue(ref vector, GetValue(defaultValue)); + PropertyInfo.Property.vectorValue = vector; + PropertyIsDefaultValue = true; + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + } + + public class VectorComponentRangeSliderItem : ShaderGUIItem + { + private readonly int _componentIndex; + private readonly Func _contentProvider; + private readonly string _rangePropertyName; + private readonly Func _isVisible; + private ShaderPropertyInfo _rangePropertyInfo; + + private const float SliderFrontGap = 5f; + private const float SliderBackGap = 2f; + + public VectorComponentRangeSliderItem( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + int componentIndex, + string rangePropertyName, + Func contentProvider, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _componentIndex = componentIndex; + _rangePropertyName = rangePropertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _isVisible = isVisible; + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void InitTriggerByChild() + { + if (!string.IsNullOrEmpty(_rangePropertyName)) + { + _rangePropertyInfo = RootItem.PropertyInfoDic[_rangePropertyName]; + } + + base.InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + using (ParentControlDisabledScope()) + { + EditorGUI.BeginChangeCheck(); + using (new EditorGUIIndentLevelScope(0)) + { + DrawController(); + } + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + OnEndChange(); + } + } + + DrawResetButton(); + } + + public override void DrawController() + { + Vector4 vector = PropertyInfo.Property.vectorValue; + Vector4 range = _rangePropertyInfo.Property.vectorValue; + float min = range.x; + float max = range.y; + float sliderMin = Mathf.Min(min, max); + float sliderMax = Mathf.Max(min, max); + float value = GetValue(vector); + + float rangeFieldWidth = EditorGUIUtility.fieldWidth; + Rect minRect = ControlRect; + minRect.width = rangeFieldWidth; + Rect maxRect = ControlRect; + maxRect.x = ControlRect.xMax - rangeFieldWidth; + maxRect.width = rangeFieldWidth; + Rect sliderRect = ControlRect; + sliderRect.x = minRect.xMax + SliderFrontGap; + sliderRect.width = Mathf.Max(0f, maxRect.x - sliderRect.x - SliderBackGap + EditorGUI.indentLevel * UnityEditorGUIIndentWidth); + + RangeVecHasMixedValue(out bool minValueHasMixed, out bool maxValueHasMixed); + + EditorGUI.showMixedValue = minValueHasMixed; + bool minAnimatedScope = BeginAnimatedPropertyBackground(minRect, _rangePropertyInfo.Property); + min = EditorGUI.FloatField(minRect, min); + EndAnimatedPropertyBackground(minAnimatedScope); + + EditorGUI.showMixedValue = maxValueHasMixed; + bool maxAnimatedScope = BeginAnimatedPropertyBackground(maxRect, _rangePropertyInfo.Property); + max = EditorGUI.FloatField(maxRect, max); + EndAnimatedPropertyBackground(maxAnimatedScope); + + range.x = min; + range.y = max; + SetVectorIfDifferent(_rangePropertyInfo.Property, range); + + sliderMin = Mathf.Min(min, max); + sliderMax = Mathf.Max(min, max); + value = DraggableLabelFloat.Handle( + LabelRect, + value, + DraggableLabelFloat.GetSensitivityByRange(sliderMin, sliderMax), + sliderMin, + sliderMax); + EditorGUI.showMixedValue = PropertyInfo.Property.hasMixedValue; + bool sliderAnimatedScope = BeginAnimatedPropertyBackground(sliderRect, PropertyInfo.Property); + value = SliderNoIndent(sliderRect, value, sliderMin, sliderMax); + EndAnimatedPropertyBackground(sliderAnimatedScope); + + SetValue(ref vector, Mathf.Clamp(value, sliderMin, sliderMax)); + SetVectorIfDifferent(PropertyInfo.Property, vector); + EditorGUI.showMixedValue = false; + } + + private static float SliderNoIndent(Rect rect, float value, float min, float max) + { + int indentLevel = EditorGUI.indentLevel; + try + { + EditorGUI.indentLevel = 0; + return EditorGUI.Slider(rect, value, min, max); + } + finally + { + EditorGUI.indentLevel = indentLevel; + } + } + + private void RangeVecHasMixedValue(out bool minValueHasMixed, out bool maxValueHasMixed) + { + minValueHasMixed = false; + maxValueHasMixed = false; + if (RootItem.Mats.Count <= 1) + { + return; + } + + float firstMin = 0f; + float firstMax = 0f; + for (int i = 0; i < RootItem.Mats.Count; i++) + { + Vector4 range = RootItem.Mats[i].GetVector(_rangePropertyName); + if (i == 0) + { + firstMin = range.x; + firstMax = range.y; + continue; + } + + if (!Mathf.Approximately(firstMin, range.x)) + { + minValueHasMixed = true; + } + + if (!Mathf.Approximately(firstMax, range.y)) + { + maxValueHasMixed = true; + } + } + } + + private float GetValue(Vector4 vector) + { + switch (_componentIndex) + { + case 0: return vector.x; + case 1: return vector.y; + case 2: return vector.z; + case 3: return vector.w; + default: return vector.x; + } + } + + private void SetValue(ref Vector4 vector, float value) + { + switch (_componentIndex) + { + case 0: + vector.x = value; + break; + case 1: + vector.y = value; + break; + case 2: + vector.z = value; + break; + case 3: + vector.w = value; + break; + } + } + + public override void CheckIsPropertyModified(bool isCallByChild = false) + { + if (!isCallByChild) + { + Vector4 defaultValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + Vector4 defaultRange = RootItem.Shader.GetPropertyDefaultVectorValue(_rangePropertyInfo.Index); + bool isDefaultValue = Mathf.Approximately(GetValue(PropertyInfo.Property.vectorValue), GetValue(defaultValue)) && + _rangePropertyInfo.Property.vectorValue == defaultRange; + if (isDefaultValue == PropertyIsDefaultValue) + { + return; + } + + PropertyIsDefaultValue = isDefaultValue; + } + + HasModified = !PropertyIsDefaultValue; + foreach (ShaderGUIItem childItem in ChildrenItemList) + { + HasModified |= childItem.HasModified; + } + + ParentItem?.CheckIsPropertyModified(true); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + Vector4 vector = PropertyInfo.Property.vectorValue; + Vector4 defaultValue = RootItem.Shader.GetPropertyDefaultVectorValue(PropertyInfo.Index); + SetValue(ref vector, GetValue(defaultValue)); + PropertyInfo.Property.vectorValue = vector; + _rangePropertyInfo.Property.vectorValue = RootItem.Shader.GetPropertyDefaultVectorValue(_rangePropertyInfo.Index); + + PropertyIsDefaultValue = true; + HasModified = false; + if (!isCallByParent) + { + ParentItem?.CheckIsPropertyModified(true); + } + } + } + + public class Vector3Item : ShaderGUIItem + { + private readonly Func _contentProvider; + private readonly Func _isVisible; + private readonly Action _onValueChanged; + + public Vector3Item( + ShaderGUIRootItem rootItem, + ShaderGUIItem parentItem, + string propertyName, + Func contentProvider, + Action onValueChanged = null, + Func isVisible = null) : base(rootItem, parentItem) + { + PropertyName = propertyName; + _contentProvider = contentProvider ?? (() => GUIContent.none); + _onValueChanged = onValueChanged; + _isVisible = isVisible; + GuiContent = _contentProvider(); + InitTriggerByChild(); + } + + public override void OnGUI() + { + if (_isVisible != null && !_isVisible()) + { + return; + } + + GetRect(); + MaterialProperty property = PropertyInfo.Property; + using (ParentControlDisabledScope()) + { + EditorGUI.LabelField(LabelRect, GuiContent); + } + + using (ParentControlDisabledScope()) + { + EditorGUI.showMixedValue = property.hasMixedValue; + EditorGUI.BeginChangeCheck(); + Vector4 vector = property.vectorValue; + Vector3 value = new Vector3(vector.x, vector.y, vector.z); + bool animatedScope = BeginAnimatedPropertyBackground(ControlRect, property); + using (new EditorGUIIndentLevelScope(0)) + { + value = EditorGUI.Vector3Field(ControlRect, GUIContent.none, value); + } + EndAnimatedPropertyBackground(animatedScope); + EditorGUI.showMixedValue = false; + if (EditorGUI.EndChangeCheck()) + { + vector.x = value.x; + vector.y = value.y; + vector.z = value.z; + property.vectorValue = vector; + OnEndChange(); + _onValueChanged?.Invoke(value); + } + } + + DrawResetButton(); + } + + public override void ExecuteReset(bool isCallByParent = false) + { + base.ExecuteReset(isCallByParent); + Vector4 vector = PropertyInfo.Property.vectorValue; + _onValueChanged?.Invoke(new Vector3(vector.x, vector.y, vector.z)); + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/VectorItem.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/VectorItem.cs.meta new file mode 100644 index 00000000..9c0ffe2c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIItems/VectorItem.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 20a960b448954fc29c9197c2357e89ec +timeCreated: 1777032000 diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIResetTool.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIResetTool.cs new file mode 100644 index 00000000..9e1fa944 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIResetTool.cs @@ -0,0 +1,426 @@ +using System.Collections.Generic; +using System; +using UnityEngine; +using UnityEngine.Rendering; +using ShaderPropertyPack = NBShaderEditor.ShaderGUIHelper.ShaderPropertyPack; +using UnityEditor; +namespace NBShaderEditor +{ + public class ShaderGUIResetTool + { + private ShaderGUIHelper _helper; + private Shader _shader; + public bool IsInitResetData = false; + + private Stack<(string,string)> _scopeContextStack = new Stack<(string,string)>(); + + public void CheckAllModifyOnValueChange() + { + foreach (var item in ResetItemDict.Values) + { + item.HasModified = item.CheckHasModifyOnValueChange(); + } + } + public void Init(ShaderGUIHelper helper) + { + _helper = helper; + _shader = helper.shader; + IsInitResetData = true; + ResetItemDict.Clear(); + _scopeContextStack.Clear(); + } + + public void EndInit() + { + IsInitResetData = false; + } + + public void Update() + { + if (_needUpdate) + { + _needUpdate = false; + CheckAllModifyOnValueChange(); + } + } + + private bool _needUpdate = false; + public void NeedUpdate() + { + _needUpdate = true; + } + + public ShaderGUIResetTool(ShaderGUIHelper helper) + { + Init(helper); + } + + public Dictionary<(string, string), ResetItem> ResetItemDict = new Dictionary<(string, string), ResetItem>(); + + public class ResetItem + { + public ResetItem Parent; + public List ChildResetItems = new List(); + public Action ResetCallBack; + public Action OnValueChangedCallBack; + public Func CheckHasModifyOnValueChange; + public Func CheckHasMixedValueOnValueChange; + public (string, string) NameTuple; + public bool HasModified = false; + public bool HasMixedValue =false; + public bool ChildHasModified = false; + public bool ChildHasMixedValue = false; + + + public void Init((string, string) nameTuple,Action resetCallBack,Action onValueChangedCallBack,Func checkHasModifyOnValueChange,Func checkHasMixedValueOnValueChange) + { + NameTuple = nameTuple; + ResetCallBack = resetCallBack; + OnValueChangedCallBack = onValueChangedCallBack; + CheckHasModifyOnValueChange = checkHasModifyOnValueChange; + CheckHasMixedValueOnValueChange = checkHasMixedValueOnValueChange; + } + + public void Execute(bool isParentCall = false) + { + ResetCallBack?.Invoke(); + OnValueChangedCallBack?.Invoke(); + HasModified = CheckHasModifyOnValueChange(); + HasMixedValue = CheckHasMixedValueOnValueChange(); + CheckOnValueChange(isParentCall); + foreach (var item in ChildResetItems) + { + item.Execute(true); + } + } + + + public void CheckOnValueChange(bool isParentCall = false) + { + HasModified = CheckHasModifyOnValueChange(); + HasMixedValue = CheckHasMixedValueOnValueChange(); + foreach (var childItem in ChildResetItems) + { + HasMixedValue |= childItem.HasMixedValue; + HasModified |= childItem.HasModified; + } + + if (!isParentCall && Parent != null) + { + Parent.CheckOnValueChange(); + } + } + } + + public void CheckOnValueChange((string,string) nameTuple) + { + if (ResetItemDict.ContainsKey(nameTuple)) + { + ResetItemDict[nameTuple].CheckOnValueChange(); + + } + else + { + Debug.LogError("不包含ResetItemDict:"+nameTuple); + } + } + + public void DrawResetModifyButton(Rect rect,(string, string) nameTuple, Action resetCallBack, + Action onValueChangedCallBack,Func checkHasModifyOnValueChange,Func checkHasMixedValueOnValueChange,bool isSharedGlobalParent = false) + { + ConstructResetItem(nameTuple,resetCallBack,onValueChangedCallBack,checkHasModifyOnValueChange,checkHasMixedValueOnValueChange,isSharedGlobalParent); + DrawResetModifyButtonFinal(rect,nameTuple); + } + public void DrawResetModifyButton(Rect rect,(string,string)nameTuple,ShaderPropertyPack pack, Action resetAction,Action onValueChangedCallBack,VectorValeType vectorValeType = VectorValeType.Undefine,bool isSharedGlobalParent = false) + { + + // (string, string) nameTuple = (label, pack.property.name); + ConstructResetItem(nameTuple, + resetAction: ()=>{ + SetPropertyToDefaultValue(pack,vectorValeType); + resetAction?.Invoke(); + },onValueChangedCallBack:onValueChangedCallBack, + checkHasModifyOnValueChange: () => IsPropertyModified(pack,vectorValeType), + checkHasMixedValueOnValueChange: () => pack.property.hasMixedValue, + isSharedGlobalParent: isSharedGlobalParent + ); + if (ResetItemDict.ContainsKey(nameTuple)) + { + DrawResetModifyButtonFinal(rect,nameTuple); + } + } + + public void DrawResetModifyButton(Rect rect, string label) + { + //大部分功能都是触发子类 + ConstructResetItem((label, ""), resetAction: () => { },onValueChangedCallBack: () => { }, () => false, () => false); + DrawResetModifyButtonFinal(rect,(label,"")); + } + + //isSharedGlobalParent==>有些组件是公用的,比如极坐标一类。这些是不会设置父Item的。 + public void ConstructResetItem((string,string) nameTuple, Action resetAction, + Action onValueChangedCallBack,Func checkHasModifyOnValueChange,Func checkHasMixedValueOnValueChange,bool isSharedGlobalParent = false) + { + if(!IsInitResetData) return; + if (!ResetItemDict.ContainsKey(nameTuple)) + { + ResetItem item = new ResetItem(); + item.Init(nameTuple,resetAction,onValueChangedCallBack,checkHasModifyOnValueChange,checkHasMixedValueOnValueChange); + ResetItemDict.Add(nameTuple,item); + + if (_scopeContextStack.Count > 0 && !isSharedGlobalParent) + { + var contextNameTuple = _scopeContextStack.Peek(); + ResetItem parentItem = ResetItemDict[contextNameTuple]; + parentItem.ChildResetItems.Add(item); + item.Parent = parentItem; + } + + if (_helper.matEditor.targets.Length == 1) + { + onValueChangedCallBack?.Invoke();//属性值初始化 + } + item.CheckOnValueChange();//Init + } + else + { + // Debug.LogError("ResetItem已经存在:"+nameTuple.ToString()); + } + //就算是已经ContainsKey了,也Push和Pop一下。没有作用,但让写法更简单。 + _scopeContextStack.Push(nameTuple); + } + + + public void EndResetModifyButtonScope() + { + if(!IsInitResetData) return; + if(_scopeContextStack.Count == 0) return; + _scopeContextStack.Pop(); + } + + public float ResetButtonSize => EditorGUIUtility.singleLineHeight; + + private GUIContent resetIconContent = new GUIContent(); + //仅仅只是Drawer + private void DrawResetModifyButtonFinal(Rect position, (string, string) nameTuple) + { + ResetItem item; + // GUILayout.FlexibleSpace(); + if (ResetItemDict.ContainsKey(nameTuple)) + { + item = ResetItemDict[nameTuple]; + } + else + { + return; + } + float btnSize = ResetButtonSize; + string iconText; + bool isDisabled = true; + GUIStyle iconStyle; + if (item.HasModified || item.HasMixedValue) + { + isDisabled = false; + iconText = "R"; + iconStyle = GUI.skin.button; + } + else + { + isDisabled = true; + iconText = ""; + iconStyle = GUI.skin.label; + } + + resetIconContent.text = iconText; + EditorGUI.BeginDisabledGroup(isDisabled); + // if (GUILayout.Button(iconTexture, GUILayout.Width(btnSize), GUILayout.Height(btnSize))) + if (position.width <= 0) + { + position = GUILayoutUtility.GetRect(resetIconContent, GUI.skin.button, GUILayout.Width(btnSize), + GUILayout.Height(btnSize)); + } + if(GUI.Button(position,resetIconContent,iconStyle)) + { + item.Execute(); + } + EditorGUI.EndDisabledGroup(); + } + + public void SetPropertyToDefaultValue(ShaderPropertyPack pack,VectorValeType vectorValeType = VectorValeType.Undefine) + { + MaterialProperty property = pack.property; + ShaderPropertyType propertyType = ShaderGUIUnityCompat.GetPropertyType(property); + if (propertyType == ShaderPropertyType.Texture && vectorValeType != VectorValeType.Undefine) + { + propertyType = ShaderPropertyType.Vector;//Tilling or Offset + } + switch (propertyType) + { + case ShaderPropertyType.Color: + Vector4 colorValue = _shader.GetPropertyDefaultVectorValue(pack.index); + property.colorValue = new Color(colorValue.x, colorValue.y, colorValue.z, colorValue.x); + break; + + case ShaderPropertyType.Vector: + Vector4 defaultVecValue; + Vector4 vecValue; + if (vectorValeType == VectorValeType.Tilling || vectorValeType == VectorValeType.Offset) + { + defaultVecValue = new Vector4(1f, 1f, 0f, 0f); + vecValue = property.textureScaleAndOffset; + + } + else + { + defaultVecValue = _shader.GetPropertyDefaultVectorValue(pack.index); + vecValue = property.vectorValue; + } + switch (vectorValeType) + { + case VectorValeType.Undefine: Debug.LogError("VectorValeType is undefined"); break; + case VectorValeType.X: vecValue.x = defaultVecValue.x;property.vectorValue = vecValue;break; + case VectorValeType.Y: vecValue.y = defaultVecValue.y;property.vectorValue = vecValue;break; + case VectorValeType.Z: vecValue.z = defaultVecValue.z;property.vectorValue = vecValue;break; + case VectorValeType.W: vecValue.w = defaultVecValue.w;property.vectorValue = vecValue;break; + case VectorValeType.XY:vecValue.x = defaultVecValue.x; vecValue.y = defaultVecValue.y; + property.vectorValue = vecValue;break; + case VectorValeType.Tilling:vecValue.x = defaultVecValue.x; vecValue.y = defaultVecValue.y; + if (ShaderGUIUnityCompat.GetPropertyType(property) == ShaderPropertyType.Texture) + { + property.textureScaleAndOffset = vecValue; + } + else + { + property.vectorValue = vecValue; + } + break; + case VectorValeType.ZW:vecValue.z = defaultVecValue.z; vecValue.w = defaultVecValue.w; + property.vectorValue = vecValue;break; + case VectorValeType.Offset:vecValue.z = defaultVecValue.z; vecValue.w = defaultVecValue.w; + if (ShaderGUIUnityCompat.GetPropertyType(property) == ShaderPropertyType.Texture) + { + property.textureScaleAndOffset = vecValue; + } + else + { + property.vectorValue = vecValue; + } + break; + case VectorValeType.XYZ:vecValue.x = defaultVecValue.x; vecValue.y = defaultVecValue.y; + vecValue.z = defaultVecValue.z; property.vectorValue = vecValue;break; + case VectorValeType.XYZW: property.vectorValue = defaultVecValue;break; + } + break; + + case ShaderPropertyType.Float or ShaderPropertyType.Range: + float value = _shader.GetPropertyDefaultFloatValue(pack.index); + property.floatValue = value; + break; + + case ShaderPropertyType.Texture: + if (property.textureValue == null) + { + break; + } + else + { + property.textureValue = null; + break; + } + // return property.textureValue.name == shader.GetPropertyTextureDefaultName(pack.index) ? false : true; + + default: + // 如果不属于上述类型,输出提示信息 + Debug.Log($"{property.displayName} has no default value or unsupported type"); + break; + } + } + + public bool IsPropertyModified(ShaderPropertyPack pack,VectorValeType vectorValeType = VectorValeType.Undefine) + { + MaterialProperty property = pack.property; + ShaderPropertyType propertyType = ShaderGUIUnityCompat.GetPropertyType(property); + if (propertyType == ShaderPropertyType.Texture && vectorValeType != VectorValeType.Undefine) + { + propertyType = ShaderPropertyType.Vector;//Tilling or Offset + } + switch (propertyType) + { + case ShaderPropertyType.Color: + Vector4 colorValue = _shader.GetPropertyDefaultVectorValue(pack.index); + Color color = new Color(colorValue.x, colorValue.y, colorValue.z, colorValue.w); + return property.colorValue == color ? false : true; + + case ShaderPropertyType.Vector: + + Vector4 defaultVecValue; + Vector4 vecValue; + if (vectorValeType == VectorValeType.Tilling || vectorValeType == VectorValeType.Offset) + { + defaultVecValue = new Vector4(1f, 1f, 0f, 0f); + if (ShaderGUIUnityCompat.GetPropertyType(property) == ShaderPropertyType.Texture) + { + vecValue = property.textureScaleAndOffset; + } + else + { + vecValue = property.vectorValue; + } + + } + else + { + defaultVecValue = _shader.GetPropertyDefaultVectorValue(pack.index); + vecValue = property.vectorValue; + } + + + Vector2 defaultVecXYValue = new Vector2(defaultVecValue.x, defaultVecValue.y); + Vector2 defaultVecZWValue = new Vector2(defaultVecValue.z, defaultVecValue.w); + Vector2 vecXYValue = new Vector2(vecValue.x, vecValue.y); + Vector2 vecZWValue = new Vector2(vecValue.z, vecValue.w); + Vector2 defaultVecXYZValue = new Vector3(defaultVecValue.x, defaultVecValue.y,defaultVecValue.z); + Vector2 vecXYZValue = new Vector3(vecValue.x, vecValue.y,vecValue.z); + + + bool isVecModified = false; + switch (vectorValeType) + { + case VectorValeType.Undefine: Debug.LogError("VectorValeType is undefined"); break; + case VectorValeType.X: isVecModified = Mathf.Approximately(vecValue.x,defaultVecValue.x) ? false : true;break; + case VectorValeType.Y: isVecModified = Mathf.Approximately(vecValue.y,defaultVecValue.y) ? false : true;break; + case VectorValeType.Z: isVecModified = Mathf.Approximately(vecValue.z,defaultVecValue.z) ? false : true;break; + case VectorValeType.W: isVecModified = Mathf.Approximately(vecValue.w,defaultVecValue.w) ? false : true;break; + case VectorValeType.XY:case VectorValeType.Tilling: + isVecModified = vecXYValue == defaultVecXYValue ? false : true;break; + case VectorValeType.ZW:case VectorValeType.Offset: + isVecModified = vecZWValue == defaultVecZWValue ? false : true;break; + case VectorValeType.XYZ:isVecModified = vecXYZValue == defaultVecXYZValue ? false : true ; break; + case VectorValeType.XYZW:isVecModified= vecValue == defaultVecValue? false : true ; break; + } + return isVecModified; + + case ShaderPropertyType.Float or ShaderPropertyType.Range: + return Mathf.Approximately(property.floatValue, _shader.GetPropertyDefaultFloatValue(pack.index)) ? false : true; + + case ShaderPropertyType.Texture: + if (property.textureValue == null) + { + return false; + } + else + { + return property.textureValue.name == "textureExternal" ? false : true; + } + // return property.textureValue.name == shader.GetPropertyTextureDefaultName(pack.index) ? false : true; + + default: + // 如果不属于上述类型,输出提示信息 + return false; + // Debug.Log($"{property.displayName} has no default value or unsupported type"); + // break; + } + } + } + +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIResetTool.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIResetTool.cs.meta new file mode 100644 index 00000000..3c1c17a4 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIResetTool.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 73135babda09451c9e5798b36897637b +timeCreated: 1754727843 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIToolBar.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIToolBar.cs new file mode 100644 index 00000000..5ce4b305 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIToolBar.cs @@ -0,0 +1,250 @@ + +using UnityEngine; +using UnityEditor; +using UnityEngine.Rendering; +using System.Collections.Generic; +using NBShader; +namespace NBShaderEditor +{ + + public class ShaderGUIToolBar + { + public ShaderGUIHelper Helper; + + private int viewModeIndex; + private readonly string[] viewModes = { "List", "Grid" }; + // private string searchText = ""; + private MaterialEditor _editor => Helper.matEditor; + public ShaderGUIToolBar(ShaderGUIHelper helper) + { + Helper = helper; + } + + private static Material copiedMaterial; + private static Shader copiedShader; + + // 帮助链接URL + private const string HELP_URL = "https://owejt9diz2c.feishu.cn/wiki/BHz8wHHSjiYJagk7WrmcAcconlb?from=from_copylink"; + + // private Vector2 imagePos; + // private Texture2D icon; + // private Texture2D image; + + public void DrawToolbar() + { + + float BtnWidth = 30f; + // 开始工具栏区域 (背景) + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + + // 1. 选择当前材质 + if (GUILayout.Button(EditorGUIUtility.IconContent("Material On Icon","跳到当前材质|跳到当前材质"), EditorStyles.toolbarButton,GUILayout.Width(BtnWidth))) + { + EditorGUIUtility.PingObject(Helper.mats[0]); + } + + if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash","清除没有使用的贴图|清除没有使用的贴图"), EditorStyles.toolbarButton,GUILayout.Width(BtnWidth))) + { + foreach (var mat in Helper.mats) + { + CleanUnusedTextureProperties(Helper.mats[0]);//先清理不属于当前Shader的贴图 + } + Helper.isClearUnUsedTexture = true; + } + + if (GUILayout.Button(new GUIContent("C","复制材质属性"), EditorStyles.toolbarButton,GUILayout.Width(BtnWidth))) + { + copiedMaterial = Helper.mats[0]; + copiedShader = copiedMaterial.shader; + } + + if (GUILayout.Button(new GUIContent("V","粘贴材质属性"), EditorStyles.toolbarButton,GUILayout.Width(BtnWidth))) + { + if (copiedShader) + { + Helper.mats[0].shader = copiedShader; + } + + if (copiedMaterial) + { + Helper.mats[0].CopyPropertiesFromMaterial(copiedMaterial); + } + } + if (GUILayout.Button(new GUIContent("R","特殊重置功能"), EditorStyles.toolbarButton,GUILayout.Width(BtnWidth))) + { + ShowResetPopupMenu(); + } + if (GUILayout.Button(EditorGUIUtility.IconContent("d_UnityEditor.HierarchyWindow","折叠所有控件|折叠所有控件"), EditorStyles.toolbarButton,GUILayout.Width(BtnWidth))) + { + for (int i = 0;i 0; + // Helper.searchText = searchText; + // } + // + // // 清除搜索按钮 + // if (GUILayout.Button("", cancelButton)) + // { + // searchText = ""; + // GUI.FocusControl(null); // 移除焦点 + // } + // } + // EditorGUILayout.EndHorizontal(); + + // // 4. 右侧按钮组 + // if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Refresh"), EditorStyles.toolbarButton)) + // { + // Debug.Log("Refresh clicked"); + // } + // + // // 选项菜单 + // if (GUILayout.Button(EditorGUIUtility.IconContent("_Popup"), EditorStyles.toolbarButton)) + // { + // // 创建下拉菜单 + // GenericMenu menu = new GenericMenu(); + // menu.AddItem(new GUIContent("Option 1"), false, () => Debug.Log("Option 1")); + // menu.AddItem(new GUIContent("Option 2"), false, () => Debug.Log("Option 2")); + // menu.ShowAsContext(); + // } + // 贴图加载 + // if (icon == null) + // icon = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath("eaa39f504c2ce7646aece103ba9c4766")); + // if (image == null) + // image = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath("cc6c30349a33a1d4c8242a9ef1a68830")); + // if (GUILayout.Button(new GUIContent(icon,"爸爸!"), EditorStyles.toolbarButton,GUILayout.Width(BtnWidth))) + // { + // // 弹出 PopupWindow + // // 弹出浮动窗口 + // FloatingImageWindow.ShowWindow(image); + // } + + + if (GUILayout.Button(EditorGUIUtility.IconContent("d__Help@2x","说明文档|说明文档"), EditorStyles.toolbarButton,GUILayout.Width(BtnWidth))) + { + // 打开浏览器跳转到帮助链接 + Application.OpenURL(HELP_URL); + } + + EditorGUILayout.EndHorizontal(); // 结束工具栏 + } + + private void ShowResetPopupMenu() + { + GenericMenu menu = new GenericMenu(); + + menu.AddItem(new GUIContent("重置特殊UV通道"), false, () => + { + Helper.ResetTool.ResetItemDict[("特殊UV通道选择","_SpecialUVChannelMode")].Execute(); + }); + menu.AddItem(new GUIContent("重置旋转扭曲"), false, () => + { + Helper.ResetTool.ResetItemDict[("","_UTwirlEnabled")].Execute(); + }); + menu.AddItem(new GUIContent("重置极坐标"), false, () => + { + Helper.ResetTool.ResetItemDict[("","_PolarCoordinatesEnabled")].Execute(); + }); + + // 弹出位置可以用 Event.current.mousePosition + menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); + } + + private void CleanUnusedTextureProperties(Material mat) + { + if (mat == null || mat.shader == null) return; + + Shader shader = mat.shader; + + // 收集 Shader 里声明过的贴图属性 + var shaderTexProps = new HashSet(); + int count = shader.GetPropertyCount(); + for (int i = 0; i < count; i++) + { + if (shader.GetPropertyType(i) == ShaderPropertyType.Texture) + { + shaderTexProps.Add(shader.GetPropertyName(i)); + } + } + + // 遍历材质所有贴图属性,找到 shader 不再声明的 + var allProps = mat.GetTexturePropertyNames(); + foreach (var propName in allProps) + { + if (!shaderTexProps.Contains(propName)) + { + if (mat.GetTexture(propName) != null) + { + mat.SetTexture(propName, null); + Debug.Log($"清理 {mat.name} 的无效贴图属性: {propName}"); + } + } + } + } + + // EditorWindow 显示图片 + public class FloatingImageWindow : EditorWindow + { + private Texture2D popupImage; + + public static void ShowWindow(Texture2D image) + { + // 创建窗口 + FloatingImageWindow window = CreateInstance(); + window.titleContent = new GUIContent("谢谢爸爸"); + window.popupImage = image; + + // 设置初始尺寸 + if (image != null) + window.position = new Rect(Screen.width / 2f - image.width / 2f, + Screen.height / 2f - image.height / 2f, + image.width, + image.height); + else + window.position = new Rect(Screen.width / 2f - 100, Screen.height / 2f - 100, 200, 200); + + window.ShowUtility(); // 浮动窗口 + } + + private void OnGUI() + { + if (popupImage != null) + { + // 绘制图片 + Rect rect = new Rect(0, 0, position.width, position.height); + GUI.DrawTexture(rect, popupImage, ScaleMode.ScaleToFit); + } + + // 可选:增加关闭按钮 + if (GUI.Button(new Rect(position.width - 25, 5, 20, 20), "X")) + { + Close(); + } + } + } + + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIToolBar.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIToolBar.cs.meta new file mode 100644 index 00000000..a9d9c689 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/ShaderGUIToolBar.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: deccdbc6963a48b2ace3358cbba67689 +timeCreated: 1754406958 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilTestHelper.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilTestHelper.cs new file mode 100644 index 00000000..16c5eb6f --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilTestHelper.cs @@ -0,0 +1,165 @@ +using System; +using UnityEngine; +using UnityEngine.Rendering; + +namespace NBShaderEditor +{ + + + [Serializable] + public class StencilValues + { + public int DefaultQueue = 2000; + [BinaryInt(8, true, 2)] public int Ref = 0; + public CompareFunction Comp = CompareFunction.Always; + public StencilOp Pass = StencilOp.Keep; + public StencilOp Fail = StencilOp.Keep; + public StencilOp ZFail = StencilOp.Keep; + [BinaryInt(8, true, 1)] public int ReadMask = 255; + [BinaryInt(8, true, 1)] public int WriteMask = 255; + } + + + + public static class StencilTestHelper + { + // private static StencilValuesConfig stencilValuesConfig; + public class StencilPropertyNames + { + public string stencil = "_Stencil"; + public string stencilComp = "_StencilComp"; + public string stencilOp = "_StencilOp"; + public string stencilWriteMask = "_StencilWriteMask"; + public string stencilReadMask = "_StencilReadMask"; + public string stencilZFail = "_StencilZFail"; + public string stencilFail = "_StencilFail"; + public string stencilKexIndex = "_StencilKeyIndex"; + + public StencilPropertyNames() + { + } + + public StencilPropertyNames(string stencilName, string stencilCompName, string stencilOpName, + string stencilWriteMaskName, string stencilReadMaskName, string stencilZFailName, + string stencilFailName, string stencilKexIndexName) + { + if (!string.IsNullOrEmpty(stencilName)) + { + stencil = stencilName; + } + + if (!string.IsNullOrEmpty(stencilCompName)) + { + stencilComp = stencilCompName; + } + + if (!string.IsNullOrEmpty(stencilOpName)) + { + stencilOp = stencilOpName; + } + + if (!string.IsNullOrEmpty(stencilWriteMaskName)) + { + stencilWriteMask = stencilWriteMaskName; + } + + if (!string.IsNullOrEmpty(stencilReadMaskName)) + { + stencilReadMask = stencilReadMaskName; + } + + if (!string.IsNullOrEmpty(stencilZFailName)) + { + stencilZFail = stencilZFailName; + } + + if (!string.IsNullOrEmpty(stencilFailName)) + { + stencilFail = stencilFailName; + } + + if (!string.IsNullOrEmpty(stencilKexIndexName)) + { + stencilKexIndex = stencilKexIndexName; + } + } + } + + + private static StencilPropertyNames defaultStencilPropertyNames = new StencilPropertyNames(); + + // public static void SetMaterialStencil(Material mat,StencilValues stencilValues,out int defaultQueue) + public static void SetMaterialStencil(Material mat, string stencilConfigKey, + StencilValuesConfig stencilValuesConfig, out int defaultQueue, + StencilPropertyNames stencilPropertyNames = null) + { + if (stencilValuesConfig == null) + { + Debug.LogError(mat.name + ": 缺少模板预设,设置Stencil失败"); + // stencilValuesConfig = + // AssetDatabase.LoadAssetAtPath( + // "Assets/AddressableAssets/Shader/StencilConfig.asset"); + } + + + if (stencilPropertyNames == null) + { + stencilPropertyNames = defaultStencilPropertyNames; + } + + StencilValues stencilValues; + if (stencilValuesConfig.ContainsKey(stencilConfigKey)) + { + stencilValues = stencilValuesConfig[stencilConfigKey]; + if (!string.IsNullOrEmpty(stencilPropertyNames.stencil)) + { + mat.SetFloat(stencilPropertyNames.stencil, stencilValues.Ref); + } + + if (!string.IsNullOrEmpty(stencilPropertyNames.stencilComp)) + { + mat.SetFloat(stencilPropertyNames.stencilComp, (float)stencilValues.Comp); + } + + if (!string.IsNullOrEmpty(stencilPropertyNames.stencilOp)) + { + mat.SetFloat(stencilPropertyNames.stencilOp, (float)stencilValues.Pass); + } + + if (!string.IsNullOrEmpty(stencilPropertyNames.stencilWriteMask)) + { + mat.SetFloat(stencilPropertyNames.stencilWriteMask, stencilValues.WriteMask); + } + + if (!string.IsNullOrEmpty(stencilPropertyNames.stencilReadMask)) + { + mat.SetFloat(stencilPropertyNames.stencilReadMask, stencilValues.ReadMask); + } + + if (!string.IsNullOrEmpty(stencilPropertyNames.stencilZFail)) + { + mat.SetFloat(stencilPropertyNames.stencilZFail, (float)stencilValues.ZFail); + } + + if (!string.IsNullOrEmpty(stencilPropertyNames.stencilFail)) + { + mat.SetFloat(stencilPropertyNames.stencilFail, (float)stencilValues.Fail); + } + + if (!string.IsNullOrEmpty(stencilPropertyNames.stencilKexIndex)) + { + mat.SetFloat(stencilPropertyNames.stencilKexIndex, + stencilValuesConfig.GetKeyIndex(stencilConfigKey)); + } + + defaultQueue = stencilValues.DefaultQueue; + } + else + { + Debug.LogError("无法设置材质模板参数,因为没有配置模板值", mat); + defaultQueue = mat.renderQueue; + } + } + } +} + diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilTestHelper.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilTestHelper.cs.meta new file mode 100644 index 00000000..5d9dbb9c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilTestHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a7d6268a1ca7d824d8da2adf4cb8f74a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilValuesConfig.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilValuesConfig.cs new file mode 100644 index 00000000..1bae9dd3 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilValuesConfig.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using NBShader; + +namespace NBShaderEditor +{ + public class StencilValuesConfig : ScriptableObject + { + // public Dictionary Config = new Dictionary(); + // public StencilValuesConfigDictionary Config = new StencilValuesConfigDictionary(); + [Serializable] + public class KeyStencilValues + { + public string key; + public StencilValues Values; + } + + [SerializeField] + public List Config = new List(); + + public bool ContainsKey(string key) + { + if (GetStencilValues(key) != null) + { + return true; + } + else + { + return false; + } + } + + public StencilValues GetStencilValues(string key) + { + foreach (var item in Config) + { + if (item.key == key) + { + return item.Values; + } + } + Debug.LogError("StencilValuesConfig: 不存在Key"+key); + return null; + } + + public int GetKeyIndex(string key) + { + for (int i = 0; i < Config.Count; i++) + { + if (Config[i].key == key) + { + return i; + } + } + Debug.LogError("StencilValuesConfig: 不存在Key"+key); + return -1; + } + + public string GetKeyByIndex(int index) + { + return Config[index].key; + } + + + public StencilValues this[string key] + { + get + { + return GetStencilValues(key); + } + } + + } + + +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilValuesConfig.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilValuesConfig.cs.meta new file mode 100644 index 00000000..a335f0b0 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StencilValuesConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9177edf81a5b2354490ec4d66c4c069d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/StringListSerchProvider.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StringListSerchProvider.cs new file mode 100644 index 00000000..c7956621 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StringListSerchProvider.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Experimental.GraphView; +using UnityEngine; +using UnityEditor; + +public class StringListSerchProvider : ScriptableObject , ISearchWindowProvider +// public class StringListSerchProvider +{ + + public List CreateSearchTree(SearchWindowContext context) + { + List serchList = new List(); + serchList.Add(new SearchTreeGroupEntry(new GUIContent("List"),0)); + List listItemAfterSort = listItems.ToList(); + + sortListItems(ref listItemAfterSort); + + List groups = new List(); + foreach (var item in listItemAfterSort) + { + string[] entryTitle = item.Split("/"); + string groupName = ""; + for (int i = 0; i < entryTitle.Length - 1; i++) + { + groupName += entryTitle[i]; + if (!groups.Contains(groupName)) + { + serchList.Add(new SearchTreeGroupEntry(new GUIContent(entryTitle[i]),i+1)); + } + groupName += "/"; + } + + SearchTreeEntry entry = new SearchTreeEntry(new GUIContent(entryTitle.Last())); + entry.level = entryTitle.Length; + entry.userData = item;//这里是serch操作点击最后的返回值,是什么都可以的。 + // Debug.Log(entry.userData); + serchList.Add(entry); + } + + + return serchList; + + } + + public bool OnSelectEntry(SearchTreeEntry searchTreeEntry, SearchWindowContext context) + { + string data = (string)searchTreeEntry.userData; + onSetIndexCallback?.Invoke(data); + return true; + } + + private string[] listItems; + private Action onSetIndexCallback; + public StringListSerchProvider(string[] items, Action callBack) + { + listItems = items; + onSetIndexCallback = callBack; + } + + public void Initialize(string[] items, Action callBack) + { + listItems = items; + onSetIndexCallback = callBack; + } + + // private List sortListItems; + + void sortListItems(ref List list) + { + // sortListItems = listItems.ToList(); + list.Sort((a, b) => + { + string[] splits1 = a.Split('/'); + string[] splits2 = b.Split('/'); + + for (int i = 0; i < splits1.Length; i++) + { + if (i >= splits2.Length) + { + return 1; + } + + int value = splits1[i].CompareTo(splits2[i]); + if (value != 0) + { + if (splits1.Length != splits2.Length && (i == splits1.Length - 1 || i == splits2.Length - 1)) + { + return splits1.Length < splits2.Length ? 1 : -1; + } + + return value; + } + } + + return 0; + }); + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/StringListSerchProvider.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StringListSerchProvider.cs.meta new file mode 100644 index 00000000..11c6efc2 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/StringListSerchProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aec459410f5254c4bb4d42e7ec8b4b5e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/VATTextureImporter.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/VATTextureImporter.cs new file mode 100644 index 00000000..66c3a656 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/VATTextureImporter.cs @@ -0,0 +1,124 @@ +using System; +using System.IO; +using UnityEditor; + +namespace NBShader.Editor +{ + public sealed class VATTextureImporter : AssetPostprocessor + { + private const string VatKeyword = "vat"; + private const string VatKeyword2 = "vertex_animation_textures"; + + private const string ExrExtension = ".exr"; + private const string PngExtension = ".png"; + private const string DefaultPlatformName = "DefaultTexturePlatform"; + private const string StandalonePlatformName = "Standalone"; + private const string AndroidPlatformName = "Android"; + private const int AndroidDataTextureMaxSize = 8192; + + private void OnPreprocessTexture() + { + if (!(assetImporter is TextureImporter textureImporter)) + { + return; + } + + if (!ShouldImport(assetPath)) + { + return; + } + + ApplyImportSettings(textureImporter); + } + + internal static bool ShouldImport(string path) + { + if (string.IsNullOrEmpty(path)) + { + return false; + } + + if (!HasSupportedExtension(path)) + { + return false; + } + + string fileName = Path.GetFileName(path); + if (string.IsNullOrEmpty(fileName)) + { + return false; + } + + bool shouldImport = false; + shouldImport |= fileName.IndexOf(VatKeyword, StringComparison.OrdinalIgnoreCase) >= 0; + shouldImport |= fileName.IndexOf(VatKeyword2, StringComparison.OrdinalIgnoreCase) >= 0; + + return shouldImport; + } + + private static bool HasSupportedExtension(string path) + { + string extension = Path.GetExtension(path); + if (string.IsNullOrEmpty(extension)) + { + return false; + } + + return extension.Equals(ExrExtension, StringComparison.OrdinalIgnoreCase) || + extension.Equals(PngExtension, StringComparison.OrdinalIgnoreCase); + } + + private static void ApplyImportSettings(TextureImporter textureImporter) + { + ApplyCommonDataSettings(textureImporter); + + string extension = Path.GetExtension(textureImporter.assetPath); + if (extension.Equals(ExrExtension, StringComparison.OrdinalIgnoreCase)) + { + ApplyPlatformSettings(textureImporter, TextureImporterFormat.RGBAHalf); + return; + } + + if (extension.Equals(PngExtension, StringComparison.OrdinalIgnoreCase)) + { + ApplyPlatformSettings(textureImporter, TextureImporterFormat.RGBA32); + } + } + + private static void ApplyCommonDataSettings(TextureImporter textureImporter) + { + textureImporter.textureType = TextureImporterType.Default; + textureImporter.sRGBTexture = false; + // textureImporter.isReadable = true; + textureImporter.mipmapEnabled = false; + textureImporter.alphaIsTransparency = false; + textureImporter.textureCompression = TextureImporterCompression.Uncompressed; + } + + private static void ApplyPlatformSettings(TextureImporter textureImporter, TextureImporterFormat format) + { + ApplyPlatformSettings(textureImporter, DefaultPlatformName, format); + ApplyPlatformSettings(textureImporter, StandalonePlatformName, format); + ApplyPlatformSettings(textureImporter, AndroidPlatformName, format); + } + + private static void ApplyPlatformSettings(TextureImporter textureImporter, string platformName, TextureImporterFormat format) + { + TextureImporterPlatformSettings settings = textureImporter.GetPlatformTextureSettings(platformName); + settings.name = platformName; + settings.overridden = true; + settings.format = format; + settings.textureCompression = TextureImporterCompression.Uncompressed; + settings.compressionQuality = 100; + settings.crunchedCompression = false; + settings.allowsAlphaSplitting = false; + if (platformName.Equals(AndroidPlatformName, StringComparison.Ordinal) && + settings.maxTextureSize < AndroidDataTextureMaxSize) + { + settings.maxTextureSize = AndroidDataTextureMaxSize; + } + + textureImporter.SetPlatformTextureSettings(settings); + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/VATTextureImporter.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/VATTextureImporter.cs.meta new file mode 100644 index 00000000..e67c2366 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/VATTextureImporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0eb1e10af3780b0499d3c7e1393a0749 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/com.xuanxuan.render.utility.Editor.asmdef b/Packages/NB_FX/XuanXuanRenderUtility/Editor/com.xuanxuan.render.utility.Editor.asmdef new file mode 100644 index 00000000..adfc75e5 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/com.xuanxuan.render.utility.Editor.asmdef @@ -0,0 +1,19 @@ +{ + "name": "com.xuanxuan.render.utility.Editor", + "rootNamespace": "", + "references": [ + "GUID:8f9e4d586616f13449cfeb86c5f704c2", + "GUID:df380645f10b7bc4b97d4f5eb6303d95" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/com.xuanxuan.render.utility.Editor.asmdef.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/com.xuanxuan.render.utility.Editor.asmdef.meta new file mode 100644 index 00000000..76c1a94a --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/com.xuanxuan.render.utility.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8495541fcd41b0c40b5b6e6e7a7639d1 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/refreshMaterialInspectorWindow.cs b/Packages/NB_FX/XuanXuanRenderUtility/Editor/refreshMaterialInspectorWindow.cs new file mode 100644 index 00000000..3cef0294 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/refreshMaterialInspectorWindow.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using UnityEditor; + +namespace NBShaderEditor +{ + public class RefreshMaterialInspectorWindow : EditorWindow + { + [MenuItem("ArtTools/刷新选中材质球面板")] + static void refershSelectMaterialInspector() + { + EditorWindow.GetWindow("材质球刷新"); + } + public static bool isRefreshing = false; + List materials = new List(); + int i = 0; + private void OnGUI() + { + if (GUILayout.Button("开始刷新材质面板")) + { + materials.Clear(); + foreach (UnityEngine.Object o in Selection.GetFiltered(typeof(Material), SelectionMode.DeepAssets)) + { + string path = AssetDatabase.GetAssetPath(o); + string fileExtension = Path.GetExtension(path); + if (fileExtension == ".mat") + { + materials.Add((Material)o); + + } + } + i = 0; + } + } + + private void OnEnable() + { + Debug.Log("刷新材质打开"); + + isRefreshing = true; + } + + private void Update() + { + if(materials.Count <= 0) return; + if (i < materials.Count) + { + // isRefreshing = true; + // SetNormalToUV1(materials[i]); + Selection.activeObject = materials[i]; + Debug.Log(materials[i].name,materials[i]); + EditorUtility.DisplayProgressBar("材质球刷新", $"{i + 1}/{materials.Count}", (i + 1) / (float)materials.Count); + i++; + // isRefreshing = false; + } + if (i >= materials.Count) + { + EditorUtility.ClearProgressBar(); + materials.Clear(); + Debug.Log("材质刷新结束,isRefreshing布尔值 = "+isRefreshing); + + } + + + } + + void OnDisable() + { + Debug.Log("刷新材质关闭"); + isRefreshing = false; + + } + + // void SetNormalToUV1(Material mat) + // { + // if (mat.HasProperty("_NormalFrom")) + // { + // mat.SetInteger("_NormalFrom",1); + // } + // } + // + // // [MenuItem("Assets/测试刷新材质", priority = 1)] + // public static void TestRefeshMaterial() + // { + // W9ParticleShaderFlags flags = new W9ParticleShaderFlags(); + // int id = Shader.PropertyToID("_Mask2_Toggle"); + // foreach (UnityEngine.Object o in Selection.GetFiltered(typeof(Material), SelectionMode.DeepAssets)) + // { + // Material mat = o as Material; + // if (mat.shader.name == "XuanXuan/Effects/Particle_NiuBi") + // { + // bool isToggle = mat.GetFloat(id) > 0.5f; + // if (isToggle) + // { + // mat.DisableKeyword("_MASKMAP2"); + // flags.SetMaterial(mat); + // flags.SetFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_MASK_MAP2,index:1); + // } + // // flags.SetMaterial(mat); + // } + // } + // AssetDatabase.SaveAssets(); + // } + // + // [MenuItem("Assets/Effect Tool/刷新选中文件夹内材质Wrap模式", priority = 1)] + // public static void SetSelectParticleMaterialWrapMode() + // { + // foreach (UnityEngine.Object o in Selection.GetFiltered(typeof(Material), SelectionMode.DeepAssets)) + // { + // Material mat = (Material)o; + // // Debug.Log(mat.shader.name); + // SetParticleMaterialWrapMode((Material)o); + // } + // AssetDatabase.SaveAssets(); + // } + // + // public static void SetParticleMaterialWrapMode(Material mat) + // { + // + // if (mat.shader.name == "XuanXuan/Effects/Particle_NiuBi") + // { + // W9ParticleShaderFlags flags = new W9ParticleShaderFlags(mat); + // SetWrapModeFlag(flags,mat,"_BaseMap",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_BASEMAP); + // SetWrapModeFlag(flags,mat,"_MaskMap",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP); + // SetWrapModeFlag(flags,mat,"_MaskMap2",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP2); + // SetWrapModeFlag(flags,mat,"_NoiseMap",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_NOISEMAP); + // SetWrapModeFlag(flags,mat,"_EmissionMap",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_EMISSIONMAP); + // SetWrapModeFlag(flags,mat,"_DissolveMap",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_MAP); + // SetWrapModeFlag(flags,mat,"_DissolveMaskMap",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP); + // SetWrapModeFlag(flags,mat,"_DissolveRampMap",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP); + // SetWrapModeFlag(flags,mat,"_ColorBlendMap",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_COLORBLENDMAP); + // SetWrapModeFlag(flags,mat,"_VertexOffset_Map",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP); + // SetWrapModeFlag(flags,mat,"_ParallaxMapping_Map",W9ParticleShaderFlags.FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP); + // } + // } + // + // public static void SetParticleMaterialMaskStrenth(Material mat) + // { + // if (mat.shader.name == "XuanXuan/Effects/Particle_NiuBi") + // { + // Vector4 vec = mat.GetVector("_MaskMap3OffsetAnition"); + // if (vec.z < 1) + // { + // Vector4 newVec = new Vector4(vec.x, vec.y, 1, vec.w); + // mat.SetVector("_MaskMap3OffsetAnition",newVec); + // } + // } + // } + // + // static void SetWrapModeFlag(W9ParticleShaderFlags flags, Material mat, string matTexPropertyName, int flagBit) + // { + // if (mat.GetTexture(matTexPropertyName) != null) + // { + // Texture tex = mat.GetTexture(matTexPropertyName); + // Debug.Log(tex.name); + // if (tex.wrapMode == TextureWrapMode.Clamp) + // { + // Debug.Log("This is Clamp"); + // flags.SetFlagBits(flagBit,index:2); + // } + // else if (tex.wrapMode == TextureWrapMode.Repeat) + // { + // Debug.Log("This is Repeat"); + // flags.ClearFlagBits(flagBit,index:2); + // } + // } + // } + + + + + // static IEnumerator refreshMaterialInspector(Material[] materials) + // { + // for (int i = 0; i < materials.Length; i++) + // { + // EditorUtility.DisplayProgressBar("材质球刷新", $"{i + 1}/{materials.Length}", (i + 1) / (float)materials.Length); + // Debug.Log(i); + // // Selection.activeObject = materials[i]; + // yield return null; + // } + // EditorUtility.ClearProgressBar(); + // // yield break; + // } + } +} + + diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Editor/refreshMaterialInspectorWindow.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Editor/refreshMaterialInspectorWindow.cs.meta new file mode 100644 index 00000000..bee009b9 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Editor/refreshMaterialInspectorWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 317bb692129be184ebd7249bba265210 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime.meta new file mode 100644 index 00000000..538ef33f --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 72e9a7523c1a5994c8fb317e7a9514e0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/AnimationSheetHelper.cs b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/AnimationSheetHelper.cs new file mode 100644 index 00000000..5563a843 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/AnimationSheetHelper.cs @@ -0,0 +1,370 @@ +using System; +using UnityEngine; +// using Sirenix.OdinInspector; +// using Unity.Mathematics; +using UnityEngine.UI; +using System.Collections.Generic; +#if UNITY_EDITOR +using UnityEditor; +#endif + +[ExecuteInEditMode] +public class AnimationSheetHelper : MonoBehaviour,IMaterialModifier +{ + + public bool isParticleBaseShader = true; + + public string propertyName = "_BaseMap_ST"; + + private int _propertyID; + private int _particleBaseAniBlendStPropertyID = Shader.PropertyToID("_BaseMap_AnimationSheetBlend_ST"); + private int _particleBaseAniBlendIntensityPropertyID = Shader.PropertyToID("_AnimationSheetHelperBlendIntensity"); + private static readonly int ParticleShaderFlagsId = Shader.PropertyToID("_W9ParticleShaderFlags"); + private static readonly int ParticleShaderFlags1Id = Shader.PropertyToID("_W9ParticleShaderFlags1"); + private static readonly int NBShaderFlagsId = Shader.PropertyToID("_NBShaderFlags"); + private static readonly int NBShaderFlags1Id = Shader.PropertyToID("_NBShaderFlags1"); + private const int FlagBitUIEffectOn = 1 << 14; + private const int FlagBitAnimationSheetHelper = 1 << 15; + private const int FlagBitUIEffectBaseMapMode = 1 << 22; + + + + // [LabelText("序列帧图横向帧数量")] + // [OnValueChanged("Init")] + public int xSize = 4; + + // [LabelText("序列帧图纵向帧数量")] + // [OnValueChanged("Init")] + public int ySize = 4; + + // [LabelText("手动控制播放")] + public bool manualPlay = false; + + // [ShowIf("manualPlay")] + // [LabelText("手动播放位置")] [Range(0, 1)] + public float manualPlayePos = 0; + + // [LabelText("播放速度fps")] + // [HideIf("manualPlay")] + public float speed = 16; + + // [ReadOnly] + // [LabelText("TillingOffset")] + public Vector4 scaleOffset; + // [ReadOnly] + public Material mat; + + // [ReadOnly] + public int frameIndex; + // [ReadOnly] + public int frameCount; + + private float _time; + + private float _xScale; + private float _yScale; + + private static List usedMaterialList = new List(); + + + // // Start is called before the first frame update + // void Start() + // { + // Debug.Log( "ASUpadate_Start"); + // Init(); + // } + private void OnEnable() + { + // Debug.Log( "ASUpadate_OnEnable"); + Init(); + #if UNITY_EDITOR + EditorApplication.update += EditorUpdate; + #endif + } + + private void OnDisable() + { + Init(); + + //清掉,避免参数保留。 + if (isParticleBaseShader) + { + if (mat) + { + GetShaderFlagIds(mat, out _, out int flags1Id); + ClearFlagBits(mat, flags1Id, FlagBitAnimationSheetHelper); + } + } + + if (usedMaterialList.Contains(mat)) + { + usedMaterialList.Remove(mat); + } + #if UNITY_EDITOR + EditorApplication.update -= EditorUpdate; + #endif + } + + // [Button("初始化")] + public void Init() + { + _time = 0; + if (xSize <= 0) + { + xSize = 1; + } + + if (ySize <= 0) + { + ySize = 1; + } + frameCount = xSize * ySize; + + _xScale = 1 / (float)xSize; + _yScale = 1 / (float)ySize; + // if (frameCount <= 0) + // { + // frameCount = 1; + // } + // scaleOffset = new Vector4(1f/(float)xSize,1f/ (float)ySize, 0, 0); + + if (gameObject.TryGetComponent(out Graphic g)) + { + if (Application.isPlaying) + { + mat = g.materialForRendering; + } + else + { + mat = g.material; + } + } + else if (gameObject.TryGetComponent(out Renderer r)) + { + if (Application.isPlaying) + { + mat = r.material; + } + else + { + mat = r.sharedMaterial; + } + // Debug.Log("AS_GetRenderer:Mat--"+mat.name); + + } + else + { + mat = null; + } + + InitParticleBaseShaderToggle(); + // InitPostProcessToggle(); + + + _propertyID = Shader.PropertyToID(propertyName); + if (mat != null) + { + mat.SetVector(_propertyID,CalSt(0)); + } + + } + + + + public void InitParticleBaseShaderToggle() + { + if (isParticleBaseShader) + { + GetShaderFlagIds(mat, out int flagsId, out int flags1Id); + // Debug.Log(CheckFlagBits(mat, ParticleShaderFlags1Id, FlagBitUIEffectBaseMapMode)); + if(CheckFlagBits(mat, flagsId, FlagBitUIEffectOn) && !CheckFlagBits(mat, flags1Id, FlagBitUIEffectBaseMapMode)) + { + propertyName = "_UI_MainTex_ST"; + } + else + { + propertyName = "_BaseMap_ST"; + } + if (mat) + { + SetFlagBits(mat, flags1Id, FlagBitAnimationSheetHelper); + } + } + // else + // { + // if (mat) + // { + // if (mat.shader.name == "Mh2/Effects/Particle_NiuBi") + // { + // _flags.SetMaterial(mat); + // _flags.ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER,index:1); + // } + // } + // } + } + + // public void InitPostProcessToggle() + // { + // if (isPostProcessShader) + // { + // TryGetComponent(out postProcessingController); + // } + // else + // { + // postProcessingController = null; + // } + // } + + + // Update is called once per frame + private int _lastIndex; + private int _nextIndex = 1; + private float _blendLerp; + private void Update() + { + // if (!isPostProcessShader)//后处理控制不通过才知。 + // { + // if(!mat || _propertyID==0) return; + // } + + + + float frameIndexFloat; + if (manualPlay) + { + float playPos = Mathf.Repeat(manualPlayePos, 1f); + frameIndexFloat = playPos * frameCount; + } + else + { + if (!Application.isPlaying) + { + #if UNITY_EDITOR + _time += (float)editorDeltaTime * speed; + #endif + } + else + { + _time += Time.deltaTime * speed; + } + frameIndexFloat = _time % frameCount; + } + frameIndex = (int) frameIndexFloat; + if (frameIndex == frameCount) + { + frameIndex = frameCount - 1; + } + + + if (_lastIndex != frameIndex) + { + // if (isPostProcessShader) + // { + // postProcessingController.distortSpeedTexSt = CalSt(frameIndex); + // } + // else + // { + mat.SetVector(_propertyID,CalSt(frameIndex)); + // } + _lastIndex = frameIndex; + _nextIndex = frameIndex + 1; + if (isParticleBaseShader) + { + mat.SetVector(_particleBaseAniBlendStPropertyID,CalSt(_nextIndex)); + } + + } + + if (isParticleBaseShader) + { + _blendLerp = Mathf.Repeat(frameIndexFloat,1f); + mat.SetFloat(_particleBaseAniBlendIntensityPropertyID,_blendLerp); + } + + } + + public Material GetModifiedMaterial(Material baseMaterial) + { + if (usedMaterialList.Contains(baseMaterial)) + { + //有可能打断UI合批,烦请客户端判断 + Material newMat = Instantiate(baseMaterial); + mat = newMat; + usedMaterialList.Add(newMat); + } + else + { + mat = baseMaterial; + usedMaterialList.Add(baseMaterial); + } + return mat; + } + + + + + private Vector4 CalSt(int index) + { + float xOffset = (index % xSize)*_xScale; + float yOffset = (ySize - index / xSize -1)*_yScale; + return new Vector4(_xScale, _yScale, xOffset, yOffset); + } + + private static void SetFlagBits(Material material, int propertyId, int bits) + { + if (!material) + { + return; + } + + material.SetInteger(propertyId, material.GetInteger(propertyId) | bits); + } + + private static void ClearFlagBits(Material material, int propertyId, int bits) + { + if (!material) + { + return; + } + + material.SetInteger(propertyId, material.GetInteger(propertyId) & ~bits); + } + + private static bool CheckFlagBits(Material material, int propertyId, int bits) + { + return material && (material.GetInteger(propertyId) & bits) != 0; + } + + private static void GetShaderFlagIds(Material material, out int flagsId, out int flags1Id) + { + if (material && (material.HasProperty(NBShaderFlagsId) || material.HasProperty(NBShaderFlags1Id))) + { + flagsId = NBShaderFlagsId; + flags1Id = NBShaderFlags1Id; + return; + } + + flagsId = ParticleShaderFlagsId; + flags1Id = ParticleShaderFlags1Id; + } + +#if UNITY_EDITOR + private double editorDeltaTime = 0; + private double lastEditorTime = 0; + void EditorUpdate() + { + + if (lastEditorTime == 0) + { + lastEditorTime = EditorApplication.timeSinceStartup; + } + editorDeltaTime = EditorApplication.timeSinceStartup - lastEditorTime; + lastEditorTime = EditorApplication.timeSinceStartup; + if (!Application.isPlaying) + { + Update(); + } + } +#endif + +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/AnimationSheetHelper.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/AnimationSheetHelper.cs.meta new file mode 100644 index 00000000..8c1de217 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/AnimationSheetHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf793623f3ea13b4db35460280cb6ded +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ButtonAttributes.cs b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ButtonAttributes.cs new file mode 100644 index 00000000..71b75844 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ButtonAttributes.cs @@ -0,0 +1,61 @@ +using System.Reflection; +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace NBShader +{ + public class InspectorButtonAttribute : PropertyAttribute + { + public string Label; + public string MethodName; + + public InspectorButtonAttribute(string label, string methodName) + { + this.Label = label; + this.MethodName = methodName; + } + } + +#if UNITY_EDITOR + [CustomPropertyDrawer(typeof(InspectorButtonAttribute))] + public class InspectorButtonPropertyDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + + InspectorButtonAttribute buttonAttribute = (InspectorButtonAttribute)attribute; + + + // 绘制按钮 + if (GUI.Button(position, buttonAttribute.Label)) + { + // 获取包含该方法的对象 + var targetObject = property.serializedObject.targetObject; + + // 获取方法信息 + var methodInfo = targetObject.GetType().GetMethod(buttonAttribute.MethodName, + BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + + if (methodInfo != null) + { + // 调用方法 + methodInfo.Invoke(targetObject, null); + } + else + { + Debug.LogError($"Method '{buttonAttribute.MethodName}' not found in {targetObject.name}."); + } + } + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + return EditorGUIUtility.singleLineHeight; // 返回按钮的高度 + } + } +#endif +} + + diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ButtonAttributes.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ButtonAttributes.cs.meta new file mode 100644 index 00000000..8897a871 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ButtonAttributes.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 45f557806bb54c4dbeaec7a2ded5be83 +timeCreated: 1737792133 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MaterialPropertyAgent.cs b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MaterialPropertyAgent.cs new file mode 100644 index 00000000..31da26e6 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MaterialPropertyAgent.cs @@ -0,0 +1,598 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.UI; + +namespace NBShader +{ + //TODO增加一键去重功能。测试排查BUG + [ExecuteInEditMode] + public class MaterialPropertyAgent : MonoBehaviour, IMaterialModifier + { + [System.Serializable] + public struct PropertyData + { + [HideInInspector] public int dataIndexInAgent; + [HideInInspector] public MaterialPropertyAgent agent; + [HideInInspector] public int id; + + + public int index; + [HideInInspector] public string propName; + + public shaderPropertyType type; + + + public string descripName; + + + public Color colorValue; + + public Vector4 vecValue; + + public float floatValue; + + [SerializeField] public IEnumerable propNameList; + [HideInInspector] public bool isActive; + [HideInInspector] public Shader shader; + [HideInInspector] public Material mat; + +#if UNITY_EDITOR + public float rangMin { get; set; } + public float rangMax { get; set; } + + public void setValueByPropChange() + { + agent.refreshShderPropNameList(); + if (!agent.isCanUsedIndex(index)) + { + index = agent.getCanUsedIndex(); + } + + string propertyName = shader.GetPropertyName(index); + id = Shader.PropertyToID(propertyName); + descripName = shader.GetPropertyDescription(index); + type = (shaderPropertyType)shader.GetPropertyType(index); + if (type == shaderPropertyType.TexEnv) + { + propName = propertyName + "_ST"; + } + else + { + propName = propertyName; + } + + switch (type) + { + case shaderPropertyType.Color: + colorValue = mat.GetColor(id); + break; + case shaderPropertyType.Float: + floatValue = mat.GetFloat(id); + break; + case shaderPropertyType.Range: + Vector2 rangeLimits = shader.GetPropertyRangeLimits(index); + rangMin = rangeLimits.x; + rangMax = rangeLimits.y; + floatValue = mat.GetFloat(id); + break; + case shaderPropertyType.Vector: + vecValue = mat.GetVector(id); + break; + case shaderPropertyType.TexEnv: + string stName = propertyName + "_ST"; + vecValue = mat.GetVector(stName); + break; + } + } + + public void inActivateThis() + { + isActive = false; + } +#endif + } + + //因为ShaderUtil只是用于Editor,所以复制一个枚举对属性类型进行识别。 + + public enum shaderPropertyType + { + // + // 摘要: + // Color Property. + Color = 0, + + // + // 摘要: + // Vector Property. + Vector = 1, + + // + // 摘要: + // Float Property. + Float = 2, + + // + // 摘要: + // Range Property. + Range = 3, + + // + // 摘要: + // Texture Property. + TexEnv = 4 + } + + + public PropertyData data0 = new PropertyData(); + + public PropertyData data1 = new PropertyData(); + + public PropertyData data2 = new PropertyData(); + + public PropertyData data3 = new PropertyData(); + + public PropertyData data4 = new PropertyData(); + + public PropertyData data5 = new PropertyData(); + + public Shader shader; + public Material mat; + + + public int materialIndex = 0; + public Renderer customRenderer; + + void initMatAndShader(bool initMat = false) + { + if (!initMat) + { + if (mat != null) return; + } + + if (customRenderer || GetComponent()) + { + Material[] materials; + Renderer r; + if (customRenderer) + { + r = customRenderer; + } + else + { + r = GetComponent(); + } + + if (Application.isPlaying) + { + materials = r.materials; + } + else + { + materials = r.sharedMaterials; + } + + mat = materials[materialIndex]; + shader = mat.shader; + } + else if (this.GetComponent()) + { + Graphic graphic = this.GetComponent(); + +//测试,要不要用IMaterialModifier来处理 + // if (Application.isPlaying) + // { + // graphic.material = Material.Instantiate(graphic.material); + // } + + mat = graphic.material; + + + shader = mat.shader; + } + else + { + Debug.LogError("MaterialPropertyAgent未找到材质", this.gameObject); + } + } + + private void Start() + { + if (Application.isPlaying) + { + initMatAndShader(true); + } + else + { + initMatAndShader(false); + } + } + + private void Update() + { + if (mat == null) + { + // initMatAndShader(); + return; + } + + updateData(data0); + updateData(data1); + updateData(data2); + updateData(data3); + updateData(data4); + updateData(data5); + } + + void updateData(PropertyData data) + { + if (!data.isActive) return; + if (mat == null) return; + switch (data.type) + { + case shaderPropertyType.Color: + mat.SetColor(data.propName, data.colorValue); + break; + case shaderPropertyType.Vector: + case shaderPropertyType.TexEnv: + mat.SetVector(data.propName, data.vecValue); + break; + case shaderPropertyType.Float: + case shaderPropertyType.Range: + mat.SetFloat(data.propName, data.floatValue); + break; + } + } + + //实际上是修改了graphic.materialForRendering + public Material GetModifiedMaterial(Material baseMaterial) + { + if (mat) + { + return mat; + } + else + { + return baseMaterial; + } + } + +#if UNITY_EDITOR + + private void OnRenderObject() + { + if (!UnityEditor.EditorApplication.isPlaying) + { + Update(); + } + } + + public void addProperteData() + { + refreshShderPropNameList(); + + if (!data0.isActive) + { + initData(ref data0, 0); + } + else if (!data1.isActive) + { + initData(ref data1, 1); + } + else if (!data2.isActive) + { + initData(ref data2, 2); + } + else if (!data3.isActive) + { + initData(ref data3, 3); + } + else if (!data4.isActive) + { + initData(ref data4, 4); + } + else if (!data5.isActive) + { + initData(ref data5, 5); + } + else + { + Debug.Log("已用掉可用的6个属性"); + } + } + + public void removeAllProperty() + { + data0.isActive = false; + data1.isActive = false; + data2.isActive = false; + data3.isActive = false; + data4.isActive = false; + data5.isActive = false; + } + + public void initData(ref PropertyData data, int dataIndexInAgent) + { + data.dataIndexInAgent = dataIndexInAgent; + data.agent = this; + data.shader = shader; + data.mat = mat; + data.isActive = true; + + data.index = getCanUsedIndex(); + data.setValueByPropChange(); + } + + #region TODO自动排除已用Property + + List usedPropertyName = new List(); + + void collectUsedPropName() + { + usedPropertyName.Clear(); + if (data0.isActive) + { + usedPropertyName.Add(data0.propName); + } + + if (data1.isActive) + { + usedPropertyName.Add(data1.propName); + } + + if (data2.isActive) + { + usedPropertyName.Add(data2.propName); + } + + if (data3.isActive) + { + usedPropertyName.Add(data3.propName); + } + + if (data4.isActive) + { + usedPropertyName.Add(data4.propName); + } + + if (data5.isActive) + { + usedPropertyName.Add(data5.propName); + } + } + + public int getCanUsedIndex() + { + int index = -1; + collectUsedPropName(); + for (int i = 0; i < shaderPropNameArr.Length; i++) + { + string propertyName; + if (shader.GetPropertyType(i) == ShaderPropertyType.Texture) + { + propertyName = shaderPropNameArr[i] + "_ST"; + } + else + { + propertyName = shaderPropNameArr[i]; + } + + if (usedPropertyName.Contains(propertyName)) continue; + index = i; + break; + } + + return index; + } + + public bool isCanUsedIndex(int i) + { + string propertyName; + if (shader.GetPropertyType(i) == ShaderPropertyType.Texture) + { + propertyName = shaderPropNameArr[i] + "_ST"; + } + else + { + propertyName = shaderPropNameArr[i]; + } + + collectUsedPropName(); + if (usedPropertyName.Contains(propertyName)) + { + return false; + } + else + { + return true; + } + } + + #endregion + + public string[] shaderPropNameArr; + public string[] shaderPropDescripArr; + public string[] shaderPropDescripsForSerch; + + private void OnValidate() + { + // if (XLuaManager.Instance != null) + // { + // if (XLuaManager.Instance.HasGameStart)//判断是游戏运行状态才进行实例化 + // { + // return;//游戏进行中不允许编辑 + // } + // } + // Debug.Log("MaterialPropertyAgent : " + "OnValidate"); + refreshShderPropNameList(); + if (TryGetComponent(out Renderer r) || customRenderer) + { + isRendererMode = true; + } + else + { + isRendererMode = false; + } + + if (TryGetComponent(out Renderer r2) || TryGetComponent(out Graphic g)) + { + isGetByComponet = true; + } + else + { + isGetByComponet = false; + } + } + + public bool isRendererMode = false; + public bool isGetByComponet = false; + + public void initMatAndShaderByMaterialIndexChange() + { + initMatAndShader(true); + refreshShderPropNameList(); + if (data0.isActive && data0.shader != mat.shader) + { + data0.shader = mat.shader; + data0.mat = mat; + } + + if (data1.isActive && data1.shader != mat.shader) + { + data1.shader = mat.shader; + data1.mat = mat; + } + + if (data2.isActive && data2.shader != mat.shader) + { + data2.shader = mat.shader; + data2.mat = mat; + } + + if (data3.isActive && data3.shader != mat.shader) + { + data3.shader = mat.shader; + data3.mat = mat; + } + + if (data4.isActive && data4.shader != mat.shader) + { + data4.shader = mat.shader; + data4.mat = mat; + } + + if (data5.isActive && data5.shader != mat.shader) + { + data5.shader = mat.shader; + data5.mat = mat; + } + + } + + + List shaderPropNameList = new List(); + private List shaderPropDescripList = new List(); + private List shaderPropDescripListForSerch = new List(); + public void refreshShderPropNameList() + { + initMatAndShader(); + if (shader == null) return; + + shaderPropNameList.Clear(); + shaderPropDescripList.Clear(); + shaderPropDescripListForSerch.Clear(); + for (int i = 0; i < shader.GetPropertyCount(); i++) + { + shaderPropNameList.Add(shader.GetPropertyName(i)); + string descript = shader.GetPropertyDescription(i); + shaderPropDescripList.Add(descript); + string lowerDesc = descript.ToLower(); + if (!(lowerDesc.Contains("ignore") || lowerDesc.Contains("mode") || lowerDesc.Contains("toggle") || + lowerDesc.Contains("enable") || lowerDesc.Contains("flag"))) + { + shaderPropDescripListForSerch.Add(descript); + } + } + + shaderPropNameArr = shaderPropNameList.ToArray(); + shaderPropDescripArr = shaderPropDescripList.ToArray(); + shaderPropDescripsForSerch = shaderPropDescripListForSerch.ToArray(); + } +#endif + } + + +/* +[CustomPropertyDrawer(typeof(MaterialPropertyAgent.PropertyData))] +public class PropertyAgentPropertyDataDrawer : PropertyDrawer +{ + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + EditorGUI.BeginProperty(position, label, property); + + var isActive = property.FindPropertyRelative("isActive"); + if (isActive.boolValue) + { + EditorGUILayout.LabelField(label, EditorStyles.boldLabel); + + EditorGUI.indentLevel++; + + EditorGUILayout.BeginHorizontal(); + var index = property.FindPropertyRelative("index"); + MaterialPropertyAgent agent = property.FindPropertyRelative("agent").objectReferenceValue as MaterialPropertyAgent; + int preservedIndex = index.intValue; + float originLabelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 80; + index.intValue = EditorGUILayout.Popup("属性名:", index.intValue, agent.shaderPropNameArr); + if (preservedIndex != index.intValue)//证明用户进行了更改 + { + if (!agent.isCanUsedIndex(index.intValue)) + { + //TODO给一个报错提示 + Debug.Log(agent.shader.GetPropertyDescription(index.intValue)); + index.intValue = agent.getCanUsedIndex(); + } + //此处进行内容刷新 + data.setValueByPropChange(); + } + + + EditorGUILayout.LabelField("属性类型:", data.type.ToString()); + + EditorGUILayout.EndHorizontal(); + EditorGUIUtility.labelWidth = originLabelWidth; + switch (data.type) + { + case MaterialPropertyAgent.shaderPropertyType.Color: + data.colorValue = EditorGUILayout.ColorField(data.descripName + " :", data.colorValue); + break; + case MaterialPropertyAgent.shaderPropertyType.Vector: + data.vecValue = EditorGUILayout.Vector4Field(data.descripName + " :", data.vecValue); + break; + case MaterialPropertyAgent.shaderPropertyType.Float: + data.floatValue = EditorGUILayout.FloatField(data.descripName + ":", data.floatValue); + break; + case MaterialPropertyAgent.shaderPropertyType.Range: + data.floatValue = EditorGUILayout.Slider(data.descripName + ":", data.floatValue, data.rangMin, data.rangMax); + break; + case MaterialPropertyAgent.shaderPropertyType.TexEnv: + data.vecValue = EditorGUILayout.Vector4Field(data.propName + "_ST:", data.vecValue); + break; + } + + if (GUILayout.Button("删除", new[] { GUILayout.Width(200) })) + { + data.isActive = false; + } + EditorGUI.indentLevel--; + EditorGUILayout.Space(); + } + } + + EditorGUI.EndProperty(); + } + +} +*/ +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MaterialPropertyAgent.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MaterialPropertyAgent.cs.meta new file mode 100644 index 00000000..2e4b6ba9 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MaterialPropertyAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 781e80efab11a1d438f7c4d37603bdff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MeshUI.cs b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MeshUI.cs new file mode 100644 index 00000000..b881e1b0 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MeshUI.cs @@ -0,0 +1,337 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace NBShader +{ + [ExecuteAlways] + [RequireComponent(typeof(CanvasRenderer))] + [AddComponentMenu("UI/Mesh UI")] + public class MeshUI : MaskableGraphic + { + [SerializeField] private Mesh mesh; + [SerializeField] private List subMeshMaterials = new List(); + + private readonly List _positions = new List(); + private readonly List _normals = new List(); + private readonly List _tangents = new List(); + private readonly List _uv0S = new List(); + private readonly List _colors = new List(); + private readonly List _subMeshIndices = new List(); + private readonly List _renderSubMeshMap = new List(); + private Mesh _workingMesh; + private int _renderSubMeshCount; + private bool _hasLoggedUnreadableMesh; + + public Mesh Mesh + { + get => mesh; + set + { + if (mesh == value) + { + return; + } + + mesh = value; + _hasLoggedUnreadableMesh = false; + SetMaterialDirty(); + SetVerticesDirty(); + } + } + + public List SubMeshMaterials => subMeshMaterials; + + public override Texture mainTexture + { + get + { + Material currentMaterial = material; + if (currentMaterial != null && currentMaterial.mainTexture != null) + { + return currentMaterial.mainTexture; + } + + return s_WhiteTexture; + } + } + + protected override void OnEnable() + { + base.OnEnable(); + SetAllDirty(); + } + + protected override void OnDisable() + { + canvasRenderer.Clear(); + base.OnDisable(); + } + + protected override void OnDestroy() + { + ReleaseWorkingMesh(); + base.OnDestroy(); + } + + protected override void OnPopulateMesh(VertexHelper vh) + { + vh.Clear(); + } + + protected override void UpdateGeometry() + { + if (canvasRenderer == null) + { + return; + } + + if (!PrepareRenderMesh(out Mesh renderMesh)) + { + canvasRenderer.Clear(); + return; + } + + canvasRenderer.SetMesh(renderMesh); + } + + protected override void UpdateMaterial() + { + if (canvasRenderer == null) + { + return; + } + + int materialCount = Mathf.Max(1, _renderSubMeshCount); + canvasRenderer.materialCount = materialCount; + + for (int i = 0; i < materialCount; i++) + { + Material sourceMaterial = GetRenderMaterial(i); + Material modifiedMaterial = sourceMaterial != null ? GetModifiedMaterial(sourceMaterial) : defaultGraphicMaterial; + canvasRenderer.SetMaterial(modifiedMaterial, i); + } + + canvasRenderer.SetTexture(mainTexture); + } + + #if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + SetMaterialDirty(); + SetVerticesDirty(); + } + #endif + + protected override void OnDidApplyAnimationProperties() + { + base.OnDidApplyAnimationProperties(); + SetVerticesDirty(); + } + + private bool PrepareRenderMesh(out Mesh renderMesh) + { + renderMesh = null; + _renderSubMeshCount = 0; + + if (mesh == null) + { + return false; + } + + if (!mesh.isReadable) + { + if (!_hasLoggedUnreadableMesh) + { + Debug.LogWarning($"MeshUI requires a read/write enabled mesh. Bake a readable mesh in the inspector before using '{mesh.name}'.", this); + _hasLoggedUnreadableMesh = true; + } + + return false; + } + + if (mesh.vertexCount <= 0) + { + return false; + } + + CollectRenderableSubMeshes(mesh, _subMeshIndices, _renderSubMeshMap); + if (_subMeshIndices.Count == 0) + { + return false; + } + + _renderSubMeshCount = _subMeshIndices.Count; + + if (ShouldUseSourceMesh()) + { + renderMesh = mesh; + return true; + } + + EnsureWorkingMesh(); + BuildWorkingMesh(); + renderMesh = _workingMesh; + return true; + } + + private bool ShouldUseSourceMesh() + { + if (color != Color.white) + { + return false; + } + + return _renderSubMeshCount == mesh.subMeshCount; + } + + private void BuildWorkingMesh() + { + Vector3[] srcVertices = mesh.vertices; + int vertexCount = srcVertices.Length; + PrepareVertexLists(vertexCount); + + Vector2[] srcUv0 = mesh.uv; + Vector3[] srcNormals = mesh.normals; + Vector4[] srcTangents = mesh.tangents; + Color32 vertexColor = color; + + for (int i = 0; i < vertexCount; i++) + { + _positions.Add(srcVertices[i]); + _uv0S.Add(srcUv0 != null && i < srcUv0.Length ? srcUv0[i] : Vector2.zero); + _normals.Add(srcNormals != null && i < srcNormals.Length ? srcNormals[i] : Vector3.back); + _tangents.Add(srcTangents != null && i < srcTangents.Length ? srcTangents[i] : new Vector4(1f, 0f, 0f, 1f)); + _colors.Add(vertexColor); + } + + _workingMesh.Clear(); + _workingMesh.indexFormat = mesh.indexFormat; + _workingMesh.SetVertices(_positions); + _workingMesh.SetNormals(_normals); + _workingMesh.SetTangents(_tangents); + _workingMesh.SetUVs(0, _uv0S); + _workingMesh.SetColors(_colors); + _workingMesh.subMeshCount = _renderSubMeshCount; + + for (int i = 0; i < _renderSubMeshCount; i++) + { + _workingMesh.SetTriangles(_subMeshIndices[i], i, false); + } + + _workingMesh.RecalculateBounds(); + } + + private static void CollectRenderableSubMeshes(Mesh sourceMesh, List subMeshIndices, List renderSubMeshMap) + { + subMeshIndices.Clear(); + renderSubMeshMap.Clear(); + + int subMeshCount = Mathf.Max(1, sourceMesh.subMeshCount); + for (int subMeshIndex = 0; subMeshIndex < subMeshCount; subMeshIndex++) + { + if (sourceMesh.GetTopology(subMeshIndex) != MeshTopology.Triangles) + { + continue; + } + + int[] indices = sourceMesh.GetTriangles(subMeshIndex); + if (indices == null || indices.Length == 0) + { + continue; + } + + subMeshIndices.Add(indices); + renderSubMeshMap.Add(subMeshIndex); + } + } + + private void PrepareVertexLists(int capacity) + { + _positions.Clear(); + _normals.Clear(); + _tangents.Clear(); + _uv0S.Clear(); + _colors.Clear(); + + if (_positions.Capacity < capacity) + { + _positions.Capacity = capacity; + } + + if (_normals.Capacity < capacity) + { + _normals.Capacity = capacity; + } + + if (_tangents.Capacity < capacity) + { + _tangents.Capacity = capacity; + } + + if (_uv0S.Capacity < capacity) + { + _uv0S.Capacity = capacity; + } + + if (_colors.Capacity < capacity) + { + _colors.Capacity = capacity; + } + } + + private void EnsureWorkingMesh() + { + if (_workingMesh != null) + { + return; + } + + _workingMesh = new Mesh + { + name = "MeshUI Generated Mesh" + }; + _workingMesh.MarkDynamic(); + } + + private void ReleaseWorkingMesh() + { + if (_workingMesh == null) + { + return; + } + + if (Application.isPlaying) + { + Destroy(_workingMesh); + } + else + { + DestroyImmediate(_workingMesh); + } + + _workingMesh = null; + } + + private Material GetRenderMaterial(int subMeshIndex) + { + int sourceSubMeshIndex = subMeshIndex; + if (subMeshIndex >= 0 && subMeshIndex < _renderSubMeshMap.Count) + { + sourceSubMeshIndex = _renderSubMeshMap[subMeshIndex]; + } + + if (subMeshMaterials != null && sourceSubMeshIndex >= 0 && sourceSubMeshIndex < subMeshMaterials.Count) + { + Material subMeshMaterial = subMeshMaterials[sourceSubMeshIndex]; + if (subMeshMaterial != null) + { + return subMeshMaterial; + } + } + + return material; + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MeshUI.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MeshUI.cs.meta new file mode 100644 index 00000000..a1c3a51e --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/MeshUI.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 96ee1f1d0f8f4cb3a4993f12831f42b7 +timeCreated: 1774387200 diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBCompatRuntimeUtility.cs b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBCompatRuntimeUtility.cs new file mode 100644 index 00000000..54037dc2 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBCompatRuntimeUtility.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +namespace NBShader +{ + public static class UnityObjectFindCompat + { + public static T FindAny() where T : Object + { +#if UNITY_2023_1_OR_NEWER + return Object.FindAnyObjectByType(); +#else +#pragma warning disable 0618 + return Object.FindObjectOfType(); +#pragma warning restore 0618 +#endif + } + + public static T[] FindAll() where T : Object + { +#if UNITY_2023_1_OR_NEWER + return Object.FindObjectsByType(FindObjectsSortMode.None); +#else +#pragma warning disable 0618 + return Object.FindObjectsOfType(); +#pragma warning restore 0618 +#endif + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBCompatRuntimeUtility.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBCompatRuntimeUtility.cs.meta new file mode 100644 index 00000000..02f62e49 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBCompatRuntimeUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6399d1dc93fb4e0c8a757240070a1313 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBParticleLocalTransformHelper.cs b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBParticleLocalTransformHelper.cs new file mode 100644 index 00000000..11701824 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBParticleLocalTransformHelper.cs @@ -0,0 +1,192 @@ +using UnityEngine; + +namespace NBShader +{ + [ExecuteAlways] + [DisallowMultipleComponent] + [RequireComponent(typeof(ParticleSystem))] + public sealed class NBParticleLocalTransformHelper : MonoBehaviour + { + private const string NBShaderName = "Effects/NBShader"; + private const string LegacyShaderName = "Effects/NBShader(Legacy)"; + private const string CustomLocalTransformKeyword = "_CUSTOM_LOCAL_TRANSFORM"; + + private static readonly int CustomLocalTransformLocalToWorldId = + Shader.PropertyToID("_CustomLocalTransformLocalToWorld"); + + private static readonly int CustomLocalTransformWorldToLocalId = + Shader.PropertyToID("_CustomLocalTransformWorldToLocal"); + + private ParticleSystemRenderer _particleRenderer; + private Material _runtimeMaterial; + private Material _lastAppliedMaterial; + private string _lastWarning; + + private void OnEnable() + { + CacheRenderer(); + ApplyCustomTransform(); + } + + private void LateUpdate() + { + ApplyCustomTransform(); + } + + private void OnValidate() + { + CacheRenderer(); + ApplyCustomTransform(); + } + + private void OnDisable() + { + SetCustomTransformKeyword(false); + } + + private void OnDestroy() + { + SetCustomTransformKeyword(false); + } + + private void CacheRenderer() + { + if (_particleRenderer == null) + { + TryGetComponent(out _particleRenderer); + } + } + + private void ApplyCustomTransform() + { + if (!TryGetWritableMaterial(out Material material)) + { + DisableLastAppliedKeyword(); + return; + } + + if (_lastAppliedMaterial != null && _lastAppliedMaterial != material) + { + _lastAppliedMaterial.DisableKeyword(CustomLocalTransformKeyword); + } + + Matrix4x4 localToWorld = transform.localToWorldMatrix; + Matrix4x4 worldToLocal = transform.worldToLocalMatrix; + + material.SetMatrix(CustomLocalTransformLocalToWorldId, localToWorld); + material.SetMatrix(CustomLocalTransformWorldToLocalId, worldToLocal); + material.EnableKeyword(CustomLocalTransformKeyword); + + _lastAppliedMaterial = material; + _lastWarning = null; + } + + private void SetCustomTransformKeyword(bool enabled) + { + Material material = GetExistingMaterial(); + if (material == null) + { + return; + } + + if (enabled) + { + material.EnableKeyword(CustomLocalTransformKeyword); + } + else + { + material.DisableKeyword(CustomLocalTransformKeyword); + if (material == _lastAppliedMaterial) + { + _lastAppliedMaterial = null; + } + } + } + + private Material GetExistingMaterial() + { + if (_lastAppliedMaterial != null) + { + return _lastAppliedMaterial; + } + + CacheRenderer(); + if (_particleRenderer == null) + { + return null; + } + + if (Application.isPlaying) + { + return _runtimeMaterial; + } + + return _particleRenderer.sharedMaterial; + } + + private bool TryGetWritableMaterial(out Material material) + { + CacheRenderer(); + if (_particleRenderer == null) + { + material = null; + LogWarningOnce("NBParticleLocalTransformHelper requires a ParticleSystemRenderer on the same GameObject."); + return false; + } + + material = Application.isPlaying ? GetRuntimeMaterial() : _particleRenderer.sharedMaterial; + if (material == null) + { + LogWarningOnce("NBParticleLocalTransformHelper could not find a material on the ParticleSystemRenderer."); + return false; + } + + if (material.shader == null || !IsSupportedShader(material.shader)) + { + material = null; + LogWarningOnce("NBParticleLocalTransformHelper only supports NBShader materials using shader '" + + NBShaderName + "' or '" + LegacyShaderName + "'."); + return false; + } + + return true; + } + + private static bool IsSupportedShader(Shader shader) + { + return shader.name == NBShaderName || shader.name == LegacyShaderName; + } + + private Material GetRuntimeMaterial() + { + if (_runtimeMaterial == null && _particleRenderer != null) + { + _runtimeMaterial = _particleRenderer.material; + } + + return _runtimeMaterial; + } + + private void DisableLastAppliedKeyword() + { + if (_lastAppliedMaterial == null) + { + return; + } + + _lastAppliedMaterial.DisableKeyword(CustomLocalTransformKeyword); + _lastAppliedMaterial = null; + } + + private void LogWarningOnce(string message) + { + if (_lastWarning == message) + { + return; + } + + _lastWarning = message; + Debug.LogWarning(message, this); + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBParticleLocalTransformHelper.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBParticleLocalTransformHelper.cs.meta new file mode 100644 index 00000000..b9f2a88c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBParticleLocalTransformHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70a2d4dce4af4875b6c1cb93bf60442d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBShaderSpriteHelper.cs b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBShaderSpriteHelper.cs new file mode 100644 index 00000000..c85d9511 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBShaderSpriteHelper.cs @@ -0,0 +1,99 @@ +using UnityEngine; +using UnityEngine.UI; +// using Sirenix.OdinInspector; +namespace NBShader +{ + [ExecuteAlways] + public class NBShaderSpriteHelper : MonoBehaviour + { + private const string NBShaderName = "Effects/NBShader"; + private const string LegacyShaderName = "Effects/NBShader(Legacy)"; + + public Sprite sprite; + + // [ReadOnly] + public SpriteRenderer spRenderer; + + // [ReadOnly] + public Image image; + + [InspectorButton("初始化", "Init")] public bool ButtomInspector; + + private Material mat; + + + + // Start is called before the first frame update + void Start() + { + Init(); + } + + void Init() + { + if (TryGetComponent(out SpriteRenderer spr)) + { + spRenderer = spr; + sprite = spr.sprite; + } + else + { + if (TryGetComponent(out Image im)) + { + image = im; + sprite = im.sprite; + } + } + + + + if (sprite) + { + Texture texture = sprite.texture; + Rect rect = sprite.textureRect; + // sharedMaterial.SetVector("_BaseMapReverseST",CalScaleOffset(spRenderer.sprite.textureRect,spRenderer.sprite.texture)); + + if (spRenderer) + { + if (Application.isPlaying) + { + mat = spRenderer.material; + } + else + { + mat = spRenderer.sharedMaterial; + } + } + else if (image) + { + mat = image.material; + } + + if (mat && IsSupportedShader(mat.shader)) + { + mat.SetVector("_MainTex_Reverse_ST", CalScaleOffset(rect, texture)); + Debug.Log(mat.name); + } + } + + + + } + + Vector4 CalScaleOffset(Rect textureRect, Texture texture) + { + //这是一个反向的scale offset。 + //算法:如果原scale offset。转换后会是 scaleAfter= 1 / scale , offsetAfter = - offset/scale; + Vector2 scaleAfter = new Vector2(texture.width / textureRect.width, texture.height / textureRect.height); + Vector2 offsetAfter = new Vector2(-(textureRect.x / texture.width) * scaleAfter.x, + -(textureRect.y / texture.height) * scaleAfter.y); + Vector4 scaleOffset = new Vector4(scaleAfter.x, scaleAfter.y, offsetAfter.x, offsetAfter.y); + return scaleOffset; + } + + private static bool IsSupportedShader(Shader shader) + { + return shader && (shader.name == NBShaderName || shader.name == LegacyShaderName); + } + } +} diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBShaderSpriteHelper.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBShaderSpriteHelper.cs.meta new file mode 100644 index 00000000..959dac85 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/NBShaderSpriteHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 58ec7ff2f9b58f5459946ac86028eacf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ShaderFlagsBase.cs b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ShaderFlagsBase.cs new file mode 100644 index 00000000..37bc4f6c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ShaderFlagsBase.cs @@ -0,0 +1,89 @@ +using System; +using UnityEngine; + +namespace NBShader +{ + public abstract class ShaderFlagsBase + { + + private Material _material; + + public Material material + { + get { return _material; } + } + + protected ShaderFlagsBase(Material material) + { + _material = material; + } + + public void SetMaterial(Material material) + { + _material = material; + } + + public Material GetMaterial() + { + return _material; + } + + public abstract int GetShaderFlagsId(int index = 0); + protected abstract string GetShaderFlagsName(int index = 0); + + private void SetIntValue(Material material, int flagBits, int index = 0) + { +#if UNITY_EDITOR + material.SetInteger(GetShaderFlagsId(index), flagBits); +#else + material.SetInteger(GetShaderFlagsId(index), flagBits); +#endif + } + + public void SetFlagBits(int flagBits, MaterialPropertyBlock propertyBlock = null, int index = 0) + { + if (propertyBlock is null) + { + if (_material is null) return; + int flags = _material.GetInteger(GetShaderFlagsId(index)); + SetIntValue(_material, flags | flagBits, index); + } + else + { + int flags = propertyBlock.GetInt(GetShaderFlagsId(index)); + propertyBlock.SetInt(GetShaderFlagsId(index), flags | flagBits); + } + } + + public void ClearFlagBits(int flagBits, MaterialPropertyBlock propertyBlock = null, int index = 0) + { + if (propertyBlock is null) + { + if (_material is null) return; + int flags = _material.GetInteger(GetShaderFlagsId(index)); + SetIntValue(_material, flags & ~flagBits, index); + } + else + { + int flags = propertyBlock.GetInteger(GetShaderFlagsId(index)); + propertyBlock.SetInteger(GetShaderFlagsId(index), flags & ~flagBits); + } + } + + public bool CheckFlagBits(int flagBits, MaterialPropertyBlock propertyBlock = null, int index = 0) + { + int flags = 0; + if (propertyBlock is null) + { + if (_material is null) throw new NullReferenceException("material"); + flags = _material.GetInteger(GetShaderFlagsId(index)); + } + else + { + flags = propertyBlock.GetInteger(GetShaderFlagsId(index)); + } + + return (flags & flagBits) != 0; + } + } +} \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ShaderFlagsBase.cs.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ShaderFlagsBase.cs.meta new file mode 100644 index 00000000..cd25db0b --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/ShaderFlagsBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3bcf591e67bd470e9375d72c63838643 +timeCreated: 1655437380 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/com.xuanxuan.render.utility.asmdef b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/com.xuanxuan.render.utility.asmdef new file mode 100644 index 00000000..04532762 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/com.xuanxuan.render.utility.asmdef @@ -0,0 +1,16 @@ +{ + "name": "com.xuanxuan.render.utility", + "rootNamespace": "", + "references": [ + "GUID:15fc0a57446b3144c949da3e2b9737a9" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Runtime/com.xuanxuan.render.utility.asmdef.meta b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/com.xuanxuan.render.utility.asmdef.meta new file mode 100644 index 00000000..58d046aa --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Runtime/com.xuanxuan.render.utility.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8f9e4d586616f13449cfeb86c5f704c2 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader.meta new file mode 100644 index 00000000..6308fd13 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 97647516635f92f43a6cd4807c3899d8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL.meta new file mode 100644 index 00000000..784e53ca --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fa89a0fdb680e154f89c18f1a7fea2c6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/HoudiniVAT.hlsl b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/HoudiniVAT.hlsl new file mode 100644 index 00000000..c4ed9279 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/HoudiniVAT.hlsl @@ -0,0 +1,521 @@ +#ifndef HOUDINI_VAT_INCLUDED +#define HOUDINI_VAT_INCLUDED + +// ───────────────────────────────────────────────────────────────────── +// Houdini VAT 3.0 — 统一实现(SoftBody / RigidBody / DynamicRemeshing / ParticleSprite) +// 集成于 ParticleBase.shader 的粒子着色器管线 +// ───────────────────────────────────────────────────────────────────── + +// ── 纹理声明 ────────────────────────────────────────────────────────── +TEXTURE2D(_posTexture); SAMPLER(sampler_posTexture); +TEXTURE2D(_posTexture2); SAMPLER(sampler_posTexture2); +TEXTURE2D(_rotTexture); SAMPLER(sampler_rotTexture); +TEXTURE2D(_colTexture); SAMPLER(sampler_colTexture); +TEXTURE2D(_lookupTable); SAMPLER(sampler_lookupTable); + +#if defined(_VAT) && defined(_VAT_HOUDINI) && \ + !defined(_HOUDINI_VAT_SOFTBODY) && \ + !defined(_HOUDINI_VAT_RIGIDBODY) && \ + !defined(_HOUDINI_VAT_DYNAMIC_REMESH) && \ + !defined(_HOUDINI_VAT_PARTICLE_SPRITE) + #define _HOUDINI_VAT_SOFTBODY +#endif + +// ── extern 材质属性(Unity 自动从材质中查找同名值) ─────────────────── + +// Playback +extern float _B_autoPlayback; +extern float _gameTimeAtFirstFrame; +extern float _playbackSpeed; +extern float _houdiniFPS; +extern float _displayFrame; +extern float _B_interpolate; +extern float _animateFirstFrame; +extern float _frameCount; + +// Bounds +extern float _boundMinX, _boundMinY, _boundMinZ; +extern float _boundMaxX, _boundMaxY, _boundMaxZ; + +// Scale +extern float _globalPscaleMul; +extern float _B_pscaleAreInPosA; + +// Particle Sprite +extern float _widthBaseScale; +extern float _heightBaseScale; +extern float _B_hideOverlappingOrigin; +extern float _originRadius; +extern float _B_CAN_SPIN; +extern float _B_spinFromHeading; +extern float _spinPhase; +extern float _scaleByVelAmount; +extern float _particleTexUScale; +extern float _particleTexVScale; + +// Flags +extern float _B_LOAD_POS_TWO_TEX; +extern float _B_UNLOAD_ROT_TEX; +extern float _B_LOAD_COL_TEX; +extern float _B_LOAD_LOOKUP_TABLE; + +// ───────────────────────────────────────────────────────────────────── +// 工具函数 +// ───────────────────────────────────────────────────────────────────── + +// 用单位四元数旋转向量 +// 公式: v' = v + 2 * cross(q.xyz, q.w*v + cross(q.xyz, v)) +float3 HVAT_RotateByQuat(float3 v, float4 q) +{ + float3 t = cross(q.xyz, v); + return v + cross(q.xyz, t + v * q.w) * 2.0; +} + +// 从 3 个最小组件重建单位四元数(RigidBody 专用) +// maxComp (0-3) 标识被省略的分量 +float4 HVAT_DecodeQuaternion(float3 xyz, float maxComp) +{ + float w = sqrt(saturate(1.0 - dot(xyz, xyz))); + float4 q = float4(xyz.x, xyz.y, xyz.z, w); + int mc = (int)maxComp; + if (mc == 1) q = float4( w, xyz.y, xyz.z, xyz.x); + else if (mc == 2) q = float4(xyz.x, -w, xyz.z, -xyz.y); + else if (mc == 3) q = float4(xyz.x, xyz.y, -w, -xyz.z); + return q; +} + +// 从 posTexture.a 解码 5-bit spheremap 压缩法线 +float3 HVAT_DecodeCompressedNormal(float posA) +{ + float scaledA = posA * 1024.0; + float xIdx = floor(scaledA / 32.0); + float yRaw = scaledA - xIdx * 32.0; + float xNorm = xIdx / 31.5; + float yNorm = yRaw / 31.5; + float2 xy = float2(xNorm, yNorm) * 4.0 - 2.0; + float d = dot(xy, xy); + float sqrtF = sqrt(saturate(1.0 - d * 0.25)); + return float3(-sqrtF * xy.x, 1.0 - d * 0.5, sqrtF * xy.y); +} + +// Lookup table 解码:从 RGBA 得到高精度采样 UV +float2 HVAT_DecodeLookupUV(float4 lookupSample, float boundMinX) +{ + float lookupHDR = (frac(-boundMinX * 10.0) >= 0.5) ? 1.0 : 0.0; + float divisor = lookupHDR ? 2048.0 : 255.0; + float lookupX = lookupSample.r + lookupSample.g / divisor; + float lookupY = 1.0 - (lookupSample.b + lookupSample.a / divisor); + return float2(lookupX, lookupY); +} + +// 计算 VAT 采样 UV +float2 HVAT_VatUV(float selectedFrame, float uv_r, float uv_g, + float oneMinusBoundMaxR, float multiplyBoundMinB, float totalFrames) +{ + float wrapped = fmod(selectedFrame - 1.0, totalFrames); + float vBase = (1.0 - uv_g) * oneMinusBoundMaxR + + (wrapped / totalFrames) * oneMinusBoundMaxR; + return float2(multiplyBoundMinB, 1.0 - vBase); +} + +// 2D hash 随机 [0, 1] +float HVAT_HashRandom2D(float2 seed) +{ + return frac(sin(dot(seed, float2(12.9898, 78.233))) * 43758.5453); +} + +// ───────────────────────────────────────────────────────────────────── +// 帧选择 +// ───────────────────────────────────────────────────────────────────── + +float2 HVAT_GetVatUV1(AttributesParticle input) +{ + return CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) + ? input.texcoords.zw + : input.Custom1.xy; +} + +void HVAT_ComputeFrameSelection(AttributesParticle input, out float selectedFrame, out float frameAlpha) +{ + float totalFrames = _frameCount; + float animTime = (_Time.y - _gameTimeAtFirstFrame) + * (_houdiniFPS / (totalFrames - 0.01)) + * _playbackSpeed; + float frameFloat = frac(animTime) * totalFrames; + + selectedFrame = _B_autoPlayback + ? floor(frameFloat) + 1.0 + : floor(_displayFrame); + frameAlpha = frac(_B_autoPlayback ? frameFloat : _displayFrame); + + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM)) + { + float frameCustomData = GetCustomData(NB_CUSTOM_DATA_FLAG_2, FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME, -1.0, input.Custom1, input.Custom2); + if (frameCustomData >= 0.0) + { + float customFrame = saturate(frameCustomData) * max(totalFrames - 1.0, 0.0) + 1.0; + selectedFrame = floor(customFrame); + frameAlpha = frac(customFrame); + } + } +} + +// ───────────────────────────────────────────────────────────────────── +// 主函数:ApplyHoudiniVAT +// ───────────────────────────────────────────────────────────────────── + +void ApplyHoudiniVAT(AttributesParticle input, inout float4 positionOS, inout float3 normalOS) +{ + // ── 共享 Bounds 常量(不依赖 UV 的部分) ── + float comparisonBoundMaxb = (frac(_boundMaxZ * 10.0) >= 0.5) ? 1.0 : 0.0; + float oneMinusBoundMaxR = 1.0 - frac(_boundMaxX * (-10.0)); + float boundMinMul10z = _boundMinZ * 10.0; + float oneMinusBoundMinB = 1.0 - (ceil(boundMinMul10z) - boundMinMul10z); + float pscaleDenom = max(1.0 - frac(_boundMaxY * 10.0), 1e-5); + + // ── 帧选择 ── + float selectedFrame, frameAlpha; + HVAT_ComputeFrameSelection(input, selectedFrame, frameAlpha); + float totalFrames = _frameCount; + + float3 boundsMax = float3(_boundMaxX, _boundMaxY, _boundMaxZ); + float3 boundsMin = float3(_boundMinX, _boundMinY, _boundMinZ); + + // ───────────────────────────────────────────────────────────────── + // Sub Mode 0: SoftBody — 加法位移 + 四元数法线 / 压缩法线 + // ───────────────────────────────────────────────────────────────── +#if defined(_HOUDINI_VAT_SOFTBODY) + { + float2 vatUV1 = HVAT_GetVatUV1(input); + float uv1r = vatUV1.r; + float uv1g = vatUV1.g; + float multiplyBoundMinB = uv1r * oneMinusBoundMinB; + + float2 texUV = HVAT_VatUV(selectedFrame, uv1r, uv1g, + oneMinusBoundMaxR, multiplyBoundMinB, totalFrames); + + // 采样位置 + float4 posSample = SAMPLE_TEXTURE2D_LOD(_posTexture, sampler_posTexture, texUV, 0); + float3 posRGB = posSample.rgb; + float posA = posSample.a; + + // 双纹理高精度位置 + if (_B_LOAD_POS_TWO_TEX > 0.5) + { + float4 pos2 = SAMPLE_TEXTURE2D_LOD(_posTexture2, sampler_posTexture2, texUV, 0); + posRGB += pos2.rgb * 0.01; + } + + // 解码位移 + float3 posDecoded = posRGB * (boundsMax - boundsMin) + boundsMin; + float3 displacement = comparisonBoundMaxb ? posRGB : posDecoded; + + // SoftBody: 原始位置 + 位移 + positionOS.xyz += displacement; + + // 法线 + if (_B_UNLOAD_ROT_TEX > 0.5) + { + normalOS = normalize(HVAT_DecodeCompressedNormal(posA)); + } + else + { + float4 rotSample = SAMPLE_TEXTURE2D_LOD(_rotTexture, sampler_rotTexture, texUV, 0); + float4 rotFinal = comparisonBoundMaxb ? rotSample : (rotSample - 0.5) * 2.0; + normalOS = normalize(HVAT_RotateByQuat(float3(0.0, 1.0, 0.0), rotFinal)); + } + + return; + } + + // ───────────────────────────────────────────────────────────────── + // Sub Mode 1: RigidBody — Pivot 旋转 + Pscale + 帧间插值 + // ───────────────────────────────────────────────────────────────── +#elif defined(_HOUDINI_VAT_RIGIDBODY) + { + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM)) + { + return; + } + + float2 vatUV1 = HVAT_GetVatUV1(input); + float uv1r = vatUV1.r; + float uv1g = vatUV1.g; + float multiplyBoundMinB = uv1r * oneMinusBoundMinB; + + // 当前帧和下一帧 UV + float2 texUV = HVAT_VatUV(selectedFrame, uv1r, uv1g, + oneMinusBoundMaxR, multiplyBoundMinB, totalFrames); + float2 texUV_next = HVAT_VatUV(selectedFrame + 1.0, uv1r, uv1g, + oneMinusBoundMaxR, multiplyBoundMinB, totalFrames); + + // 采样旋转 + float4 rotSample = SAMPLE_TEXTURE2D_LOD(_rotTexture, sampler_rotTexture, texUV, 0); + float4 rotRemapped = (rotSample - 0.5) * 2.0; + float4 rotFinal = comparisonBoundMaxb ? rotSample : rotRemapped; + + // 采样位置 + float4 posSample = SAMPLE_TEXTURE2D_LOD(_posTexture, sampler_posTexture, texUV, 0); + float3 posRGB = posSample.rgb; + float posA = posSample.a; + + // 四元数 maxComp 索引(从 posA 整数部分) + float quatMaxIdxScaled = posA * 4.0; + float quatMaxIdx = floor(quatMaxIdxScaled); + + // 解码四元数 + float4 q = HVAT_DecodeQuaternion(rotFinal.rgb, quatMaxIdx); + + // 解码位置 + float3 posRawForDecode = posRGB; + if (_B_LOAD_POS_TWO_TEX > 0.5) + { + float4 pos2 = SAMPLE_TEXTURE2D_LOD(_posTexture2, sampler_posTexture2, texUV, 0); + posRawForDecode = posRGB + pos2.rgb * 0.01; + } + + float3 posDecoded = posRawForDecode * (boundsMax - boundsMin) + boundsMin; + float3 piecePos = comparisonBoundMaxb ? posRawForDecode : posDecoded; + + // Pscale + float pscaleFromPosA = (1.0 - frac(quatMaxIdxScaled)) / pscaleDenom; + float pscale = (_B_pscaleAreInPosA > 0.5) ? pscaleFromPosA : 1.0; + float totalScale = _globalPscaleMul * pscale; + + // Rest pivot 从 UV2/UV3 + // Custom2 = TEXCOORD2 (uv2), vatTexcoord5 = TEXCOORD4 (uv3) + float3 restPivot = float3(-input.Custom2.r, input.vatTexcoord5.r, 1.0 - input.vatTexcoord5.g); + + // 旋转局部偏移 + float3 localOffset = positionOS.xyz - restPivot; + float3 rotatedLocal = HVAT_RotateByQuat(localOffset, q); + float3 scaledLocal = rotatedLocal * totalScale; + + // 帧间插值 + float3 finalPiecePos = piecePos; + if (_B_interpolate > 0.5) + { + float4 posSampleNext = SAMPLE_TEXTURE2D_LOD(_posTexture, sampler_posTexture, texUV_next, 0); + float3 posRGBNext = posSampleNext.rgb; + if (_B_LOAD_POS_TWO_TEX > 0.5) + { + float4 pos2Next = SAMPLE_TEXTURE2D_LOD(_posTexture2, sampler_posTexture2, texUV_next, 0); + posRGBNext += pos2Next.rgb * 0.01; + } + float3 posDecodedNext = posRGBNext * (boundsMax - boundsMin) + boundsMin; + float3 piecePosNext = comparisonBoundMaxb ? posRGBNext : posDecodedNext; + finalPiecePos = lerp(piecePos, piecePosNext, frameAlpha); + } + + // 组装最终位置 + float3 animatedPos = scaledLocal + finalPiecePos; + + // 首帧复位 + float wrappedForCheck = fmod(selectedFrame - 1.0, totalFrames); + bool isRestFrame = (wrappedForCheck < 0.5) && !(_animateFirstFrame > 0.5); + float3 finalPosOS = isRestFrame ? positionOS.xyz : animatedPos; + + // 崩塌:无 piece 关联 + finalPosOS = (uv1g <= 0.1) ? float3(0, 0, 0) : finalPosOS; + + // 法线 + float3 rotatedNormalOS = isRestFrame + ? normalOS + : normalize(HVAT_RotateByQuat(normalOS, q)); + normalOS = rotatedNormalOS; + + positionOS.xyz = finalPosOS; + return; + } + + // ───────────────────────────────────────────────────────────────── + // Sub Mode 2: DynamicRemeshing — Lookup Table → 绝对位置 + // ───────────────────────────────────────────────────────────────── +#elif defined(_HOUDINI_VAT_DYNAMIC_REMESH) + { + // 使用 uv0 (texcoords.r/g) 作为 piece UV + float uv0r = input.texcoords.r; + float uv0g = input.texcoords.g; + float multiplyBoundMinB = uv0r * oneMinusBoundMinB; + + float2 vatUV = HVAT_VatUV(selectedFrame, uv0r, uv0g, + oneMinusBoundMaxR, multiplyBoundMinB, totalFrames); + + // Lookup Table + float4 lookupSample = SAMPLE_TEXTURE2D_LOD(_lookupTable, sampler_lookupTable, vatUV, 0); + float2 lookupUV = HVAT_DecodeLookupUV(lookupSample, _boundMinX); + + // 采样位置(绝对坐标) + float4 posSample = SAMPLE_TEXTURE2D_LOD(_posTexture, sampler_posTexture, lookupUV, 0); + float3 posRGB = posSample.rgb; + float posA = posSample.a; + + // 双纹理高精度位置 + if (_B_LOAD_POS_TWO_TEX > 0.5) + { + float4 pos2 = SAMPLE_TEXTURE2D_LOD(_posTexture2, sampler_posTexture2, lookupUV, 0); + posRGB += pos2.rgb * 0.01; + } + + // 解码绝对位置 + float3 posDecoded = posRGB * (boundsMax - boundsMin) + boundsMin; + float3 finalPosOS = comparisonBoundMaxb ? posRGB : posDecoded; + + // 无有效 piece 塌陷 + finalPosOS = (uv0g <= 0.1) ? float3(0, 0, 0) : finalPosOS; + + positionOS.xyz = finalPosOS; + + // 法线 + if (_B_UNLOAD_ROT_TEX > 0.5) + { + normalOS = normalize(HVAT_DecodeCompressedNormal(posA)); + } + else + { + float4 rotSample = SAMPLE_TEXTURE2D_LOD(_rotTexture, sampler_rotTexture, lookupUV, 0); + float4 rotFinal = comparisonBoundMaxb ? rotSample : (rotSample - 0.5) * 2.0; + normalOS = normalize(HVAT_RotateByQuat(float3(0.0, 1.0, 0.0), rotFinal)); + } + + return; + } + + // ───────────────────────────────────────────────────────────────── +#elif defined(_HOUDINI_VAT_PARTICLE_SPRITE) + // Sub Mode 3: ParticleSprite — Billboard + Spin + Origin Mask + // ───────────────────────────────────────────────────────────────── + { + float2 vatUV1 = HVAT_GetVatUV1(input); + float uv1r = vatUV1.r; + float uv1g = vatUV1.g; + float multiplyBoundMinB = uv1r * oneMinusBoundMinB; + + // 当前帧 + 下一帧 UV + float2 vatUV = HVAT_VatUV(selectedFrame, uv1r, uv1g, + oneMinusBoundMaxR, multiplyBoundMinB, totalFrames); + float2 vatUV_next = HVAT_VatUV(selectedFrame + 1.0, uv1r, uv1g, + oneMinusBoundMaxR, multiplyBoundMinB, totalFrames); + + // 采样位置 + float4 posSample = SAMPLE_TEXTURE2D_LOD(_posTexture, sampler_posTexture, vatUV, 0); + float4 posSample_next = SAMPLE_TEXTURE2D_LOD(_posTexture, sampler_posTexture, vatUV_next, 0); + + float3 posRGB = posSample.rgb; + float3 posRGB_next = posSample_next.rgb; + float posA = posSample.a; + float posA_next = posSample_next.a; + + // 双纹理高精度位置 + if (_B_LOAD_POS_TWO_TEX > 0.5) + { + float4 pos2 = SAMPLE_TEXTURE2D_LOD(_posTexture2, sampler_posTexture2, vatUV, 0); + float4 pos2_next = SAMPLE_TEXTURE2D_LOD(_posTexture2, sampler_posTexture2, vatUV_next, 0); + posRGB += pos2.rgb * 0.01; + posRGB_next += pos2_next.rgb * 0.01; + } + + // 解码粒子中心 + float3 posDecoded = posRGB * (boundsMax - boundsMin) + boundsMin; + float3 posDecoded_next = posRGB_next * (boundsMax - boundsMin) + boundsMin; + + float3 particlePos = comparisonBoundMaxb ? posRGB : posDecoded; + float3 particlePos_next = comparisonBoundMaxb ? posRGB_next : posDecoded_next; + + // 帧间插值 + float3 particlePosF = (_B_interpolate > 0.5) + ? lerp(particlePos, particlePos_next, frameAlpha) + : particlePos; + + // Pscale + float posA_f = (_B_interpolate > 0.5) ? lerp(posA, posA_next, frameAlpha) : posA; + float pscaleRaw = posA_f / pscaleDenom; + + // 每粒子随机缩放 + float perParticleRandom = HVAT_HashRandom2D(float2(uv1r, uv1g)); + float additionalPscaleMul = 1.0 + perParticleRandom; + + // 原点遮挡 mask + float distThis = distance(particlePos, float3(0, 0, 0)); + float distNext = distance(particlePos_next, float3(0, 0, 0)); + float maskThis = saturate(sign(distThis - _originRadius)); + float maskNext = saturate(sign(distNext - _originRadius)); + float maskF = (_B_interpolate > 0.5) ? lerp(maskThis, maskNext, frameAlpha) : maskThis; + + float pscaleFinal; + if (_B_pscaleAreInPosA > 0.5) + { + pscaleFinal = (_B_hideOverlappingOrigin > 0.5) + ? pscaleRaw * _globalPscaleMul * additionalPscaleMul * maskF + : pscaleRaw * _globalPscaleMul * additionalPscaleMul; + } + else + { + pscaleFinal = (_B_hideOverlappingOrigin > 0.5) + ? _globalPscaleMul * additionalPscaleMul * maskF + : _globalPscaleMul * additionalPscaleMul; + } + + // Billboard 方向轴 + float3 viewRight = float3(1, 0, 0); + float3 viewUp = float3(0, 1, 0); + float velStretch = 1.0; + float3 headingViewDir = float3(0, 0, 0); + + if (_B_CAN_SPIN > 0.5) + { + // 从颜色通道读取 heading + if (_B_LOAD_COL_TEX > 0.5) + { + float4 colThis = SAMPLE_TEXTURE2D_LOD(_colTexture, sampler_colTexture, vatUV, 0); + headingViewDir = float3(-colThis.r, colThis.g, colThis.b); + } + + if (_B_spinFromHeading > 0.5) + { + float2 hXY = headingViewDir.xy; + float hLen = length(hXY); + float2 hDir = (hLen > 1e-5) ? hXY / hLen : float2(1, 0); + viewRight = float3(hDir.x, hDir.y, 0); + viewUp = cross(viewRight, float3(0, 0, -1)); + velStretch = _scaleByVelAmount * hLen; + } + else + { + float angle = frac(_spinPhase) * 6.283185; + float c = cos(angle); + float s = sin(angle); + viewRight = float3(c, s, 0); + viewUp = cross(viewRight, float3(0, 0, -1)); + } + } + + // 视图空间 → 世界空间 → 物体空间 + float3 worldRight = mul((float3x3)UNITY_MATRIX_I_V, viewRight); + float3 worldUp = mul((float3x3)UNITY_MATRIX_I_V, viewUp); + float3 worldFwd = mul((float3x3)UNITY_MATRIX_I_V, float3(0, 0, 1)); + + float3 rightOS = normalize(TransformWorldToObjectDir(worldRight)); + float3 upOS = normalize(TransformWorldToObjectDir(worldUp)); + float3 normalOS_new = normalize(TransformWorldToObjectDir(worldFwd)); + + // Billboard 顶点偏移 + float cornerX = input.texcoords.r - 0.5; + float cornerY = input.texcoords.g - 0.5; + + float3 offsetX = rightOS * cornerX * _widthBaseScale * pscaleFinal; + float3 offsetY = upOS * cornerY * _heightBaseScale * pscaleFinal * velStretch; + + float3 finalPosOS = particlePosF + offsetX + offsetY; + + // 崩塌 + finalPosOS = (uv1g <= 0.1) ? float3(0, 0, 0) : finalPosOS; + + positionOS.xyz = finalPosOS; + normalOS = normalOS_new; + return; + } +#endif +} + +#endif // HOUDINI_VAT_INCLUDED diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/HoudiniVAT.hlsl.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/HoudiniVAT.hlsl.meta new file mode 100644 index 00000000..c0cdc5d6 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/HoudiniVAT.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 802859f4f9ef96442bf245ade4894f0d +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl new file mode 100644 index 00000000..b9157d02 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl @@ -0,0 +1,356 @@ +#ifndef SIX_WAY_SMOKE_LIT_HLSL +#define SIX_WAY_SMOKE_LIT_HLSL +//这部分尽量借鉴 UnityEditor.VFX.HDRP.SixWaySmokeLit + +#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" + +// Generated from UnityEditor.VFX.HDRP.SixWaySmokeLit+BSDFData +// PackingRules = Exact +struct BSDFData +{ + uint materialFeatures; + float absorptionRange; + real4 diffuseColor; + real3 fresnel0; + real ambientOcclusion; + float3 normalWS; + float4 tangentWS; + real3 geomNormalWS; + real3 rigRTBk; + real3 rigLBtF; + real3 bakeDiffuseLighting0;//rigRTBk.x + real3 bakeDiffuseLighting1;//rigRTBk.y + real3 bakeDiffuseLighting2;// bsdfData.tangentWS.w > 0.0f ? rigRTBk.z : rigLBtF.z + real3 backBakeDiffuseLighting0;//rigLBtF.x + real3 backBakeDiffuseLighting1;//rigLBtF.y + real3 backBakeDiffuseLighting2;// bsdfData.tangentWS.w > 0.0f ? rigLBtF.z : rigRTBk.z + + //-----NBShaders----- + real3 emission; + real emissionInput;//NegativeTex.a + real alpha;//PositiveTex.a + +}; + +#define ABSORPTION_EPSILON max(REAL_MIN, 1e-5) + +real3 ComputeDensityScales(real3 absorptionColor) +{ + absorptionColor.rgb = max(ABSORPTION_EPSILON, absorptionColor.rgb); + + // Empirical value used to parametrize absorption from color + const real absorptionStrength = 0.2f; + return 1.0f + log2(absorptionColor.rgb) / log2(absorptionStrength); +} + +real3 GetTransmissionWithAbsorption(real transmission, real4 absorptionColor, real absorptionRange) +{ + #if defined(VFX_SIX_WAY_ABSORPTION) + real3 densityScales = ComputeDensityScales(absorptionColor.rgb); + + #ifdef VFX_BLENDMODE_PREMULTIPLY + absorptionRange *= (absorptionColor.a > 0) ? absorptionColor.a : 1.0f; + #endif + + // real3 outTransmission = GetTransmissionWithAbsorption(transmission, densityScales, absorptionRange); + real3 outTransmission = pow(saturate(transmission / absorptionRange), densityScales); + outTransmission *= absorptionRange; + + return outTransmission; + #else + return transmission.xxx * absorptionColor.rgb; // simple multiply + #endif +} + +void ModifyBakedDiffuseLighting(BSDFData bsdfData, inout float3 bakeDiffuseLighting) +{ + bakeDiffuseLighting = 0; + + // Scale to be energy conserving: Total energy = 4*pi; divided by 6 directions + float scale = 4.0f * PI / 6.0f; + + float3 frontBakeDiffuseLighting = bsdfData.tangentWS.w > 0.0f ? bsdfData.bakeDiffuseLighting2 : bsdfData.backBakeDiffuseLighting2; + float3 backBakeDiffuseLighting = bsdfData.tangentWS.w > 0.0f ? bsdfData.backBakeDiffuseLighting2 : bsdfData.bakeDiffuseLighting2; + + float3x3 bakeDiffuseLightingMat; + bakeDiffuseLightingMat[0] = bsdfData.bakeDiffuseLighting0; + bakeDiffuseLightingMat[1] = bsdfData.bakeDiffuseLighting1; + bakeDiffuseLightingMat[2] = frontBakeDiffuseLighting; + bakeDiffuseLighting += GetTransmissionWithAbsorption(bsdfData.rigRTBk.x, bsdfData.diffuseColor, bsdfData.absorptionRange) * bakeDiffuseLightingMat[0]; + bakeDiffuseLighting += GetTransmissionWithAbsorption(bsdfData.rigRTBk.y, bsdfData.diffuseColor, bsdfData.absorptionRange) * bakeDiffuseLightingMat[1]; + bakeDiffuseLighting += GetTransmissionWithAbsorption(bsdfData.rigRTBk.z, bsdfData.diffuseColor, bsdfData.absorptionRange) * bakeDiffuseLightingMat[2]; + + bakeDiffuseLightingMat[0] = bsdfData.backBakeDiffuseLighting0; + bakeDiffuseLightingMat[1] = bsdfData.backBakeDiffuseLighting1; + bakeDiffuseLightingMat[2] = backBakeDiffuseLighting; + bakeDiffuseLighting += GetTransmissionWithAbsorption(bsdfData.rigLBtF.x, bsdfData.diffuseColor, bsdfData.absorptionRange) * bakeDiffuseLightingMat[0]; + bakeDiffuseLighting += GetTransmissionWithAbsorption(bsdfData.rigLBtF.y, bsdfData.diffuseColor, bsdfData.absorptionRange) * bakeDiffuseLightingMat[1]; + bakeDiffuseLighting += GetTransmissionWithAbsorption(bsdfData.rigLBtF.z, bsdfData.diffuseColor, bsdfData.absorptionRange) * bakeDiffuseLightingMat[2]; + + bakeDiffuseLighting *= scale; + +} + +//世界空间到切线空间方向转换 +float3 TransformToLocalFrame(float3 L, BSDFData bsdfData) +{ + float3 zVec = -bsdfData.normalWS; + float3 xVec = bsdfData.tangentWS.xyz; + float3 yVec = -cross(zVec, xVec) * bsdfData.tangentWS.w;//原代码没有负值,实际测试需要负值 + float3x3 tbn = float3x3(xVec, yVec, zVec); + return mul(tbn, L); +} + +CBSDF EvaluateBSDF(float3 L, BSDFData bsdfData) +{ + CBSDF cbsdf; + ZERO_INITIALIZE(CBSDF, cbsdf); + + float3 dir = TransformToLocalFrame(L, bsdfData); + float3 weights = dir >= 0 ? bsdfData.rigRTBk.xyz : bsdfData.rigLBtF.xyz; + float3 sqrDir = dir*dir; + + cbsdf.diffR = GetTransmissionWithAbsorption(dot(sqrDir, weights), bsdfData.diffuseColor, bsdfData.absorptionRange); + + return cbsdf; +} + + +//这一步最好在面板上做完 +half GetAbsorptionRange(float absorptionStrenth) +{ + return INV_PI + saturate(absorptionStrenth) * (1 - INV_PI); +} + + + + +//---------NBShaderUtility----------- + +//UseInVerTex +void GetSixWayBakeDiffuseLight(real3 normalWS,real3 tangentWS,real3 biTangentWS, + inout half3 bakeDiffuseLighting0,inout half3 bakeDiffuseLighting1,inout half3 bakeDiffuseLighting2, + inout half3 backBakeDiffuseLighting0,inout half3 backBakeDiffuseLighting1,inout half3 backBakeDiffuseLighting2) +{ + bakeDiffuseLighting0 = SampleSHVertex(tangentWS); + bakeDiffuseLighting1 = SampleSHVertex(biTangentWS); + bakeDiffuseLighting2 = SampleSHVertex(-normalWS); + backBakeDiffuseLighting0 = SampleSHVertex(-tangentWS); + backBakeDiffuseLighting1 = SampleSHVertex(-biTangentWS); + backBakeDiffuseLighting2 = SampleSHVertex(normalWS); +} + +LightingData CreateSixWayLightingData(InputData inputData, half3 emission) +{ + LightingData lightingData; + + lightingData.giColor = inputData.bakedGI; + lightingData.emissionColor = emission; + lightingData.vertexLightingColor = 0; + lightingData.mainLightColor = 0; + lightingData.additionalLightsColor = 0; + + return lightingData; +} + +void GetSixWayEmission(inout BSDFData bsdfData,Texture2D rampMap,half4 emissionColor,bool isRampMap) +{ + float input = pow(bsdfData.emissionInput,_SixWayInfo.y); + half3 emission = emissionColor * emissionColor.a; + if (isRampMap) + { + half4 rampSample = rampMap.Sample(sampler_linear_clamp,half2(input,0.5)); + emission = emission * rampSample * rampSample.a; + } + else + { + emission *= input; + } + bsdfData.emission = emission; +} + +half3 LightingSixWay(Light light,InputData inputData, BSDFData bsdfData) +{ + half3 cbsdf_R = EvaluateBSDF(light.direction,bsdfData).diffR; + half3 radiance = light.color * light.distanceAttenuation * light.shadowAttenuation; + return PI * cbsdf_R * radiance; +} + + +//光照流程--->原型为UniversalFragmentBlinnPhong +half4 UniversalFragmentSixWay(InputData inputData,BSDFData bsdfData) +{ + // #if defined(DEBUG_DISPLAY) + // half4 debugColor; + // + // if (CanDebugOverrideOutputColor(inputData, surfaceData, debugColor)) + // { + // return debugColor; + // } + // #endif + +#ifdef _LIGHT_LAYERS + uint meshRenderingLayers = GetMeshRenderingLayer(); +#endif + half4 shadowMask = CalculateShadowMask(inputData); + // AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData); + AmbientOcclusionFactor aoFactor; + aoFactor.directAmbientOcclusion = 1; + aoFactor.indirectAmbientOcclusion = 1; + Light mainLight = GetMainLight(inputData, shadowMask, aoFactor); + + // MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, aoFactor); + + // inputData.bakedGI *= surfaceData.albedo; + + // LightingData lightingData = CreateLightingData(inputData, surfaceData); + LightingData lightingData = CreateSixWayLightingData(inputData,bsdfData.emission); + +#ifdef _LIGHT_LAYERS + if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers)) +#endif + { + lightingData.mainLightColor += LightingSixWay(mainLight, inputData, bsdfData); + } + + #if defined(_ADDITIONAL_LIGHTS) + uint pixelLightCount = GetAdditionalLightsCount(); + + #if USE_FORWARD_PLUS + for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++) + { + FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK + + Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor); +#ifdef _LIGHT_LAYERS + if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers)) +#endif + { + lightingData.additionalLightsColor += LightingSixWay(light, inputData, bsdfData); + } + } + #endif + + LIGHT_LOOP_BEGIN(pixelLightCount) + Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor); +#ifdef _LIGHT_LAYERS + if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers)) +#endif + { + lightingData.additionalLightsColor += LightingSixWay(light, inputData, bsdfData); + } + LIGHT_LOOP_END + #endif + + #if defined(_ADDITIONAL_LIGHTS_VERTEX) + lightingData.vertexLightingColor += inputData.vertexLighting * surfaceData.albedo; + #endif + + return CalculateFinalColor(lightingData, bsdfData.alpha); +} +half3 LightingHalfLambert(half3 lightColor, half3 lightDir, half3 normal) +{ + half NdotL = saturate(dot(normal, lightDir)); + NdotL = NdotL*0.5 + 0.5; + return lightColor * NdotL; +} +half3 CalculateHalfLambertBlinnPhong(Light light, InputData inputData, SurfaceData surfaceData) +{ + half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation); + half3 lightDiffuseColor = LightingHalfLambert(attenuatedLightColor, light.direction, inputData.normalWS); + + half3 lightSpecularColor = half3(0,0,0); + #if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR) + half smoothness = exp2(10 * surfaceData.smoothness + 1); + + lightSpecularColor += LightingSpecular(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, half4(surfaceData.specular, 1), smoothness); + #endif + + #if _ALPHAPREMULTIPLY_ON + return lightDiffuseColor * surfaceData.albedo * surfaceData.alpha + lightSpecularColor; + #else + return lightDiffuseColor * surfaceData.albedo + lightSpecularColor; + #endif +} +half4 UniversalFragmentHalfLambert(InputData inputData, half3 diffuse, half4 specularGloss, half smoothness, half3 emission, half alpha, half3 normalTS) +{ + + SurfaceData surfaceData; + + surfaceData.albedo = diffuse; + surfaceData.alpha = alpha; + surfaceData.emission = emission; + surfaceData.metallic = 0; + surfaceData.occlusion = 1; + surfaceData.smoothness = smoothness; + surfaceData.specular = specularGloss.rgb; + surfaceData.clearCoatMask = 0; + surfaceData.clearCoatSmoothness = 1; + surfaceData.normalTS = normalTS; + + + // #if defined(DEBUG_DISPLAY) + // half4 debugColor; + // + // if (CanDebugOverrideOutputColor(inputData, surfaceData, debugColor)) + // { + // return debugColor; + // } + // #endif + + #ifdef _LIGHT_LAYERS + uint meshRenderingLayers = GetMeshRenderingLayer(); + #endif + + half4 shadowMask = CalculateShadowMask(inputData); + AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData); + Light mainLight = GetMainLight(inputData, shadowMask, aoFactor); + + MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, aoFactor); + + inputData.bakedGI *= surfaceData.albedo; + + LightingData lightingData = CreateLightingData(inputData, surfaceData); +#ifdef _LIGHT_LAYERS + if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers)) +#endif + { + lightingData.mainLightColor += CalculateHalfLambertBlinnPhong(mainLight, inputData, surfaceData); + } + + #if defined(_ADDITIONAL_LIGHTS) + uint pixelLightCount = GetAdditionalLightsCount(); + + #if USE_FORWARD_PLUS + for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++) + { + FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK + + Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor); +#ifdef _LIGHT_LAYERS + if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers)) +#endif + { + lightingData.additionalLightsColor += CalculateBlinnPhong(light, inputData, surfaceData); + } + } + #endif + + LIGHT_LOOP_BEGIN(pixelLightCount) + Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor); +#ifdef _LIGHT_LAYERS + if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers)) +#endif + { + lightingData.additionalLightsColor += CalculateHalfLambertBlinnPhong(light, inputData, surfaceData); + } + LIGHT_LOOP_END + #endif + + #if defined(_ADDITIONAL_LIGHTS_VERTEX) + lightingData.vertexLightingColor += inputData.vertexLighting * surfaceData.albedo; + #endif + + return CalculateFinalColor(lightingData, surfaceData.alpha); +} +#endif diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl.meta new file mode 100644 index 00000000..99e32ec5 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/SixWaySmokeLit.hlsl.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 70e94bdedafe40bfb7f8e77cdc4bef0f +timeCreated: 1751704445 \ No newline at end of file diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/TyflowVAT.hlsl b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/TyflowVAT.hlsl new file mode 100644 index 00000000..3ba8f05c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/TyflowVAT.hlsl @@ -0,0 +1,585 @@ +#ifndef TYFLOW_VAT_INCLUDED +#define TYFLOW_VAT_INCLUDED + +#define TYFLOW_VAT_SKIN_MAX_BONES 7 + +#if defined(_VAT) && defined(_VAT_TYFLOW) && \ + !defined(_TYFLOW_VAT_ABSOLUTE) && \ + !defined(_TYFLOW_VAT_RELATIVE) && \ + !defined(_TYFLOW_VAT_SKIN_R) && \ + !defined(_TYFLOW_VAT_SKIN_PR) && \ + !defined(_TYFLOW_VAT_SKIN_PRSAVE) && \ + !defined(_TYFLOW_VAT_SKIN_PRSXYZ) + #define _TYFLOW_VAT_ABSOLUTE +#endif + +#if defined(_TYFLOW_VAT_SKIN_R) || \ + defined(_TYFLOW_VAT_SKIN_PR) || \ + defined(_TYFLOW_VAT_SKIN_PRSAVE) || \ + defined(_TYFLOW_VAT_SKIN_PRSXYZ) + #define TYFLOW_VAT_SKIN_MODE +#endif + +struct TyflowVatMatrix3 +{ + float3 row0; + float3 row1; + float3 row2; + float3 row3; +}; + +struct TyflowVatTMParts +{ + float3 pos; + float4 rot; + float3 scale; +}; + +inline int TyflowVatUnpackIntRGBA(int4 bytes) +{ + return ((bytes.x << 24) + (bytes.y << 16) + (bytes.z << 8) + (bytes.w << 0)); +} + +inline float TyflowVatUnpackFloatRGBA(int4 bytes) +{ + int sign = (bytes.r & 128) > 0 ? -1 : 1; + + int expR = (bytes.r & 127) << 1; + int expG = bytes.g >> 7; + int exponent = expR + expG; + + int signifG = (bytes.g & 127) << 16; + int signifB = bytes.b << 8; + + float significand = (signifG + signifB + bytes.a) / pow(2, 23); + significand += 1; + + return sign * significand * pow(2, exponent - 127); +} + +inline half TyflowVatUnpackHalfRGBA(int2 bytes) +{ + uint value = (bytes.x << 8) | bytes.y; + + uint sign = (value & 0x8000) > 0; + int exponent = (value & 0x7C00) >> 10; + uint mantissa = (value & 0x03FF); + + if ((value & 0x7FFF) == 0) + { + return sign ? -0 : 0; + } + + if (exponent == 0x001F) + { + if (mantissa == 0) + { + return sign ? -1e+28 : 1e+28; + } + + return 1e+28; + } + + if (exponent > 0) + { + float result = pow(2.0, exponent - 15) * (1 + mantissa * (1 / 1024.0f)); + return sign ? -result : result; + } + + float subnormal = pow(2.0, -24) * mantissa; + return sign ? -subnormal : subnormal; +} + +float4 TyflowVatSampleTexel(uint x, uint y) +{ + float2 uv = float2( + ((float)x + 0.5f) * _VATTex_TexelSize.x, + 1.0f - (((float)y + 0.5f) * _VATTex_TexelSize.y)); + + return SAMPLE_TEXTURE2D_LOD(_VATTex, sampler_point_clamp, uv, 0); +} + +float4 TyflowVatSampleEncodedTexel(uint x, uint y) +{ + float4 sample = TyflowVatSampleTexel(x, y); + + if (_LinearToGamma > 0.5f) + { + sample.r = LinearToGammaSpaceExact(sample.r); + sample.g = LinearToGammaSpaceExact(sample.g); + sample.b = LinearToGammaSpaceExact(sample.b); + } + + return sample; +} + +int TyflowVatTex2DInt(int arrInx) +{ + uint width = (uint)_VATTex_TexelSize.z; + uint x = (uint)arrInx % width; + uint y = (uint)arrInx / width; + + float4 bytes = TyflowVatSampleEncodedTexel(x, y); + int4 byteInts = int4(round(bytes.x * 255), round(bytes.y * 255), round(bytes.z * 255), round(bytes.w * 255)); + return TyflowVatUnpackIntRGBA(byteInts.wzyx); +} + +float TyflowVatTex2DFloat(int arrInx) +{ + uint width = (uint)_VATTex_TexelSize.z; + uint x = (uint)arrInx % width; + uint y = (uint)arrInx / width; + + float4 bytes = TyflowVatSampleEncodedTexel(x, y); + int4 byteInts = int4(round(bytes.x * 255), round(bytes.y * 255), round(bytes.z * 255), round(bytes.w * 255)); + return TyflowVatUnpackFloatRGBA(byteInts.wzyx); +} + +half TyflowVatTex2DHalf(float arrInxF) +{ + uint arrInx = (uint)floor(arrInxF + 0.1f); + uint width = (uint)_VATTex_TexelSize.z; + uint x = arrInx % width; + uint y = arrInx / width; + + float4 bytes = TyflowVatSampleEncodedTexel(x, y); + int4 byteInts = int4(round(bytes.x * 255), round(bytes.y * 255), round(bytes.z * 255), round(bytes.w * 255)); + + if (abs(arrInxF - round(arrInxF)) > 0.25f) + { + return TyflowVatUnpackHalfRGBA(byteInts.wz); + } + + return TyflowVatUnpackHalfRGBA(byteInts.yx); +} + +half2 TyflowVatTex2DHalfs2(float arrInxF) +{ + uint arrInx = (uint)floor(arrInxF + 0.1f); + uint width = (uint)_VATTex_TexelSize.z; + uint x = arrInx % width; + uint y = arrInx / width; + + float4 bytes = TyflowVatSampleEncodedTexel(x, y); + int4 byteInts = int4(round(bytes.x * 255), round(bytes.y * 255), round(bytes.z * 255), round(bytes.w * 255)); + + return half2(TyflowVatUnpackHalfRGBA(byteInts.yx), TyflowVatUnpackHalfRGBA(byteInts.wz)); +} + +float3 TyflowVatMultiplyPosition(TyflowVatMatrix3 matrixValue, float3 pos) +{ + return float3( + pos.x * matrixValue.row0[0] + pos.y * matrixValue.row1[0] + pos.z * matrixValue.row2[0] + matrixValue.row3[0], + pos.x * matrixValue.row0[1] + pos.y * matrixValue.row1[1] + pos.z * matrixValue.row2[1] + matrixValue.row3[1], + pos.x * matrixValue.row0[2] + pos.y * matrixValue.row1[2] + pos.z * matrixValue.row2[2] + matrixValue.row3[2]); +} + +TyflowVatMatrix3 TyflowVatQuaternionToTM(float4 quat) +{ + TyflowVatMatrix3 matrixValue; + + float x = quat.x; + float y = quat.y; + float z = quat.z; + float w = quat.w; + + matrixValue.row0[0] = 1 - 2 * (y * y + z * z); + matrixValue.row0[1] = 2 * (x * y + z * w); + matrixValue.row0[2] = 2 * (x * z - y * w); + + matrixValue.row1[0] = 2 * (x * y - z * w); + matrixValue.row1[1] = 1 - 2 * (x * x + z * z); + matrixValue.row1[2] = 2 * (y * z + x * w); + + matrixValue.row2[0] = 2 * (x * z + y * w); + matrixValue.row2[1] = 2 * (y * z - x * w); + matrixValue.row2[2] = 1 - 2 * (x * x + y * y); + + matrixValue.row3 = float3(0, 0, 0); + + return matrixValue; +} + +TyflowVatMatrix3 TyflowVatScaleTM(TyflowVatMatrix3 matrixValue, float3 scale) +{ + matrixValue.row0 *= scale.x; + matrixValue.row1 *= scale.y; + matrixValue.row2 *= scale.z; + return matrixValue; +} + +TyflowVatMatrix3 TyflowVatTranslateTM(TyflowVatMatrix3 matrixValue, float3 translation) +{ + matrixValue.row3 = translation; + return matrixValue; +} + +float4 TyflowVatQlerp(float4 a, float4 b, float blend) +{ + float s1 = 1.0f - blend; + float s2 = dot(a, b) < 0.0f ? -blend : blend; + + return normalize(float4( + s1 * a.x + s2 * b.x, + s1 * a.y + s2 * b.y, + s1 * a.z + s2 * b.z, + s1 * a.w + s2 * b.w)); +} + +int TyflowVatGetMetaDataSize() +{ + #if defined(_TYFLOW_VAT_SKIN_PRSXYZ) + return 12; + #else + if (_DeformingSkin > 0.5f) + { + return 12; + } + + return 3; + #endif +} + +float3 TyflowVatGetTMPos(float startIndex) +{ + float3 result; + for (int i = 0; i < 3; i++) + { + result[i] = TyflowVatTex2DFloat(startIndex + i); + } + + return result; +} + +float4 TyflowVatGetTMRot(float startIndex) +{ + half2 rotHalfs1 = TyflowVatTex2DHalfs2(startIndex); + half2 rotHalfs2 = TyflowVatTex2DHalfs2(startIndex + 1); + + return float4(-rotHalfs1.x, -rotHalfs1.y, -rotHalfs2.x, rotHalfs2.y); +} + +float3 TyflowVatGetTMScaleXYZ(float startIndex) +{ + half2 scaleHalfs1 = TyflowVatTex2DHalfs2(startIndex); + half2 scaleHalfs2 = TyflowVatTex2DHalfs2(startIndex + 1); + + return float3(scaleHalfs1.x, scaleHalfs1.y, scaleHalfs2.x); +} + +float3 TyflowVatGetTMScaleAve(float startIndex) +{ + half scaleHalf = TyflowVatTex2DHalf(startIndex); + return float3(scaleHalf, scaleHalf, scaleHalf); +} + +TyflowVatMatrix3 TyflowVatTMFromParts(TyflowVatTMParts parts) +{ + TyflowVatMatrix3 matrixValue = TyflowVatQuaternionToTM(parts.rot); + matrixValue = TyflowVatScaleTM(matrixValue, parts.scale); + matrixValue = TyflowVatTranslateTM(matrixValue, parts.pos); + return matrixValue; +} + +TyflowVatMatrix3 TyflowVatGetVertexInvTM(int tmInx) +{ + TyflowVatMatrix3 matrixValue; + int pixelsPerTM = TyflowVatGetMetaDataSize(); + + float tmRowInx = 2 + (pixelsPerTM * tmInx); + matrixValue.row0 = TyflowVatGetTMPos(tmRowInx); + tmRowInx += 3; + matrixValue.row1 = TyflowVatGetTMPos(tmRowInx); + tmRowInx += 3; + matrixValue.row2 = TyflowVatGetTMPos(tmRowInx); + tmRowInx += 3; + matrixValue.row3 = TyflowVatGetTMPos(tmRowInx); + + return matrixValue; +} + +TyflowVatTMParts TyflowVatGetVertexTMPartsAtFrame(int tmInx, int frame, int numTMs) +{ + float4 rot = float4(0, 0, 0, 1); + float3 pos = float3(0, 0, 0); + float3 scale = float3(1, 1, 1); + + float pixelsPerTM = 0; + #if defined(_TYFLOW_VAT_SKIN_R) + pixelsPerTM = 2; + #elif defined(_TYFLOW_VAT_SKIN_PR) + pixelsPerTM = 5; + #elif defined(_TYFLOW_VAT_SKIN_PRSXYZ) + pixelsPerTM = 7; + #elif defined(_TYFLOW_VAT_SKIN_PRSAVE) + pixelsPerTM = 6; + #endif + + float frameTMInx = (2 + numTMs * TyflowVatGetMetaDataSize()) + (frame * numTMs * pixelsPerTM) + (pixelsPerTM * tmInx); + + #if defined(_TYFLOW_VAT_SKIN_R) + pos = TyflowVatGetTMPos(2 + tmInx * TyflowVatGetMetaDataSize()); + rot = TyflowVatGetTMRot(frameTMInx); + #elif defined(_TYFLOW_VAT_SKIN_PR) + pos = TyflowVatGetTMPos(frameTMInx); + frameTMInx += 3; + rot = TyflowVatGetTMRot(frameTMInx); + #elif defined(_TYFLOW_VAT_SKIN_PRSXYZ) + pos = TyflowVatGetTMPos(frameTMInx); + frameTMInx += 3; + rot = TyflowVatGetTMRot(frameTMInx); + frameTMInx += 2; + scale = TyflowVatGetTMScaleXYZ(frameTMInx); + #elif defined(_TYFLOW_VAT_SKIN_PRSAVE) + pos = TyflowVatGetTMPos(frameTMInx); + frameTMInx += 3; + rot = TyflowVatGetTMRot(frameTMInx); + frameTMInx += 2; + scale = TyflowVatGetTMScaleAve(frameTMInx); + #endif + + TyflowVatTMParts parts; + parts.pos = pos; + parts.rot = rot; + parts.scale = scale; + return parts; +} + +float4 TyflowVatGetVertexValueAtFrame(uint vertexIndex, int vertexCount, int frame, int frameOffset) +{ + float4 result = float4(0, 0, 0, 0); + + vertexIndex += (vertexCount * frame) + (vertexCount * frameOffset); + + if (_RGBAEncoded > 0.5f) + { + if (_RGBAHalf > 0.5f) + { + vertexIndex *= 3; + for (int i = 0; i < 3; i++) + { + float arrInxF = (vertexIndex + i) * 0.5f; + result[i] = TyflowVatTex2DHalf(arrInxF); + } + } + else + { + vertexIndex *= 3; + for (int i = 0; i < 3; i++) + { + result[i] = TyflowVatTex2DFloat(vertexIndex + i); + } + } + } + else + { + uint width = (uint)_VATTex_TexelSize.z; + uint x = vertexIndex % width; + uint y = vertexIndex / width; + result = TyflowVatSampleTexel(x, y); + } + + return result; +} + +float3 TyflowVatGetLocalVertexPosFromTM(float3 pos, TyflowVatMatrix3 invTM) +{ + float3 localPos = ((pos / _ImportScale) * float3(-1, 1, 1)); + return TyflowVatMultiplyPosition(invTM, localPos); +} + +float3 TyflowVatGetLocalVertexPosFromPos(float3 pos, float boneInx) +{ + int tmInx = 2 + (int)round(boneInx) * TyflowVatGetMetaDataSize(); + float3 tmPos = float3(0, 0, 0); + + for (int i = 0; i < 3; i++) + { + tmPos[i] = TyflowVatTex2DFloat(tmInx + i); + } + + return ((pos / _ImportScale) * float3(-1, 1, 1)) - tmPos; +} + +float2 TyflowVatGetSkinTexcoord(AttributesParticle input, int index) +{ + if (index == 0) return input.Custom1.xy; + if (index == 1) return input.Custom2.xy; + #if !defined(_FLIPBOOKBLENDING_ON) + if (index == 2) return input.vatTexcoord4; + #endif + if (index == 3) return input.vatTexcoord5; + if (index == 4) return input.vatTexcoord6; + if (index == 5) return input.vatTexcoord7; + if (index == 6) return input.vatTexcoord8; + return float2(0, 0); +} + +void ApplyTyflowVAT(AttributesParticle input, inout float4 positionOS, inout float3 normalOS) +{ + #if defined(SHADOWS_DEPTH) + if (_AffectsShadows < 0.5f) + { + return; + } + #endif + + float frameBase = _Frame; + float frameCustomData = GetCustomData(NB_CUSTOM_DATA_FLAG_2, FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME, -1.0f, input.Custom1, input.Custom2); + if (frameCustomData >= 0.0f) + { + frameBase = saturate(frameCustomData) * max(_Frames - 1.0f, 0.0f); + } + + float frame = abs(frameBase + ((_Autoplay > 0.5f) ? (time * 30.0f * _AutoplaySpeed) : 0.0f)); + frame = (_Loop > 0.5f) ? fmod(frame, _Frames) : min(frame, _Frames - 1.0f); + + if ((_Loop > 0.5f) && (_InterpolateLoop < 0.5f) && (frame >= _Frames - 1.0f)) + { + frame = _Frames - 1.0f; + } + + uint frame0 = (uint)floor(frame); + uint frame1 = (uint)ceil(frame) % (uint)_Frames; + float frameInterp = frame - frame0; + + #if defined(TYFLOW_VAT_SKIN_MODE) + if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM)) + { + return; + } + else + { + int numTMs = TyflowVatTex2DInt(1); + float3 combinedPos = float3(0, 0, 0); + float3 combinedNormal = float3(0, 0, 0); + int loopCount = (_DeformingSkin > 0.5f) ? (int)_SkinBoneCount : 1; + + [unroll] + for (int i = 0; i < TYFLOW_VAT_SKIN_MAX_BONES; i++) + { + if (i >= loopCount) + { + break; + } + + float weight = 1.0f; + float tmInx = round(input.Custom1.y); + + if (_DeformingSkin > 0.5f) + { + float2 texcoord = TyflowVatGetSkinTexcoord(input, i); + tmInx = round(texcoord.x); + weight = texcoord.y; + } + + TyflowVatTMParts tmParts0 = TyflowVatGetVertexTMPartsAtFrame((int)tmInx, frame0, numTMs); + + if (_FrameInterpolation > 0.5f) + { + TyflowVatTMParts tmParts1 = TyflowVatGetVertexTMPartsAtFrame((int)tmInx, frame1, numTMs); + tmParts0.pos = lerp(tmParts0.pos, tmParts1.pos, frameInterp); + tmParts0.rot = TyflowVatQlerp(tmParts0.rot, tmParts1.rot, frameInterp); + tmParts0.scale = lerp(tmParts0.scale, tmParts1.scale, frameInterp); + } + + TyflowVatMatrix3 tm = TyflowVatTMFromParts(tmParts0); + TyflowVatMatrix3 invStartTM; + + #if defined(_TYFLOW_VAT_SKIN_PRSXYZ) + bool useInvStartTM = true; + #else + bool useInvStartTM = _DeformingSkin > 0.5f; + #endif + + if (useInvStartTM) + { + invStartTM = TyflowVatGetVertexInvTM((int)tmInx); + } + else + { + invStartTM.row0 = float3(0, 0, 0); + invStartTM.row1 = float3(0, 0, 0); + invStartTM.row2 = float3(0, 0, 0); + invStartTM.row3 = float3(0, 0, 0); + } + + float3 localPos; + if (useInvStartTM) + { + localPos = TyflowVatGetLocalVertexPosFromTM(positionOS.xyz, invStartTM); + } + else + { + localPos = TyflowVatGetLocalVertexPosFromPos(positionOS.xyz, tmInx); + } + + float3 pos = TyflowVatMultiplyPosition(tm, localPos) * float3(-1, 1, 1); + combinedPos += (pos * _ImportScale) * weight; + + #if !defined(SHADOWS_DEPTH) + { + float3 animatedNormal = normalOS; + tm.row3 = float3(0, 0, 0); + + if (useInvStartTM) + { + invStartTM.row3 = float3(0, 0, 0); + float3 localNormal = TyflowVatGetLocalVertexPosFromTM(animatedNormal, invStartTM); + animatedNormal = normalize(TyflowVatMultiplyPosition(tm, localNormal)) * float3(-1, 1, 1); + } + else + { + tm = TyflowVatTranslateTM(tm, float3(0, 0, 0)); + animatedNormal = normalize(TyflowVatMultiplyPosition(tm, animatedNormal * float3(-1, 1, 1))) * float3(-1, 1, 1); + } + + combinedNormal += animatedNormal * weight; + } + #endif + } + + positionOS.xyz = combinedPos; + normalOS = combinedNormal; + } + #elif defined(_TYFLOW_VAT_ABSOLUTE) || defined(_TYFLOW_VAT_RELATIVE) + { + float2 tyflowVatIndexData = CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM) + ? input.texcoords.zw + : input.Custom1.xy; + uint vertexIndex = (uint)round(tyflowVatIndexData.x); + uint vertexCount = (uint)round(tyflowVatIndexData.y); + + float4 vertexOffset0 = TyflowVatGetVertexValueAtFrame(vertexIndex, vertexCount, frame0, 0); + float4 vertexOffset = vertexOffset0; + + if (_FrameInterpolation > 0.5f) + { + float4 vertexOffset1 = TyflowVatGetVertexValueAtFrame(vertexIndex, vertexCount, frame1, 0); + vertexOffset = lerp(vertexOffset0, vertexOffset1, frameInterp); + } + + #if defined(_TYFLOW_VAT_RELATIVE) + positionOS.xyz += (vertexOffset * float4(-1, 1, 1, 1) * _ImportScale).xyz; + #else + positionOS.xyz = (vertexOffset * float4(-1, 1, 1, 1) * _ImportScale).xyz; + #endif + + #if !defined(SHADOWS_DEPTH) + if (_VATIncludesNormals > 0.5f) + { + float4 normal0 = TyflowVatGetVertexValueAtFrame(vertexIndex, vertexCount, frame0, (int)_Frames); + float4 animatedNormal = normal0; + if (_FrameInterpolation > 0.5f) + { + float4 normal1 = TyflowVatGetVertexValueAtFrame(vertexIndex, vertexCount, frame1, (int)_Frames); + animatedNormal = lerp(normal0, normal1, frameInterp) * float4(-1, 1, 1, 1); + } + normalOS = normalize(animatedNormal.xyz); + } + #endif + } + #endif +} + +#endif diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/TyflowVAT.hlsl.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/TyflowVAT.hlsl.meta new file mode 100644 index 00000000..fc4d150f --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/TyflowVAT.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e5bde8a4dd9946d4ab49c8b1f3bc6d12 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl new file mode 100644 index 00000000..fc47fe2e --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl @@ -0,0 +1,23 @@ +#ifndef PARTICLE_VAT_INCLUDED +#define PARTICLE_VAT_INCLUDED + +#include "HoudiniVAT.hlsl" +#include "TyflowVAT.hlsl" + +void ApplyVAT(AttributesParticle input, inout float4 positionOS, inout float3 normalOS) +{ +#if defined(_VAT) + if (_VAT_Toggle < 0.5f) + { + return; + } + + #if defined(_VAT_HOUDINI) + ApplyHoudiniVAT(input, positionOS, normalOS); + #elif defined(_VAT_TYFLOW) + ApplyTyflowVAT(input, positionOS, normalOS); + #endif +#endif +} + +#endif diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl.meta new file mode 100644 index 00000000..0445b353 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/VAT.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a0126cd1b294e894f9ac10e46b7776d6 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl new file mode 100644 index 00000000..ff90d9d6 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/XuanXuan_Utility.hlsl @@ -0,0 +1,391 @@ +#ifndef XUANXUAN_UTILITY +#define XUANXUAN_UTILITY + + + +//引入自UnityCG.cginc +#define UNITY_PI 3.14159265359f +#define UNITY_TWO_PI 6.28318530718f +#define UNITY_FOUR_PI 12.56637061436f +#define UNITY_INV_PI 0.31830988618f +#define UNITY_INV_TWO_PI 0.15915494309f +#define UNITY_INV_FOUR_PI 0.07957747155f +#define UNITY_HALF_PI 1.57079632679f +#define UNITY_INV_HALF_PI 0.636619772367f + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" + +inline half NB_Remap(half x, half inMin, half inMax, half outMin, half outMax) +{ + // x= clamp(x,inMin,inMax); + return saturate((x - inMin) / (inMax - inMin)) * (outMax - outMin) + outMin; +} + +inline half NB_Remap01(half x, half inMin, half inMax) +{ + // x= clamp(x,inMin,inMax); + return saturate((x - inMin) / (inMax - inMin)); +} + +inline half NB_RemapNoClamp(half x, half inMin, half inMax, half outMin, half outMax) +{ + // x= clamp(x,inMin,inMax); + return ((x - inMin) / (inMax - inMin)) * (outMax - outMin) + outMin; +} + +//原生SmoothStep开销很大:https://zhuanlan.zhihu.com/p/34629262 +//在很多时候可以用简单线性映射代替。 +half SimpleSmoothstep(half min,half max,half interp) +{ + return saturate((interp - min)/(max-min)); +} + +half4 TryLinearize(half4 color) +{ + #if defined(UNITY_COLORSPACE_GAMMA) + return pow(color, 2.2f); + #else + return color; + #endif +} + +half4 TryLinearizeWithoutAlpha(half4 color) +{ + #if defined(UNITY_COLORSPACE_GAMMA) + return half4(pow(color.rgb, 2.2f), color.a); + #else + return color; + #endif +} + +half3 TryLinearize(half3 color) +{ + #if defined(UNITY_COLORSPACE_GAMMA) + return pow(color, 2.2f); + #else + return color; + #endif +} + +half2 TryLinearize(half2 color) +{ + #if defined(UNITY_COLORSPACE_GAMMA) + return pow(color, 2.2f); + #else + return color; + #endif +} + +half TryLinearize(half color) +{ + #if defined(UNITY_COLORSPACE_GAMMA) + return pow(color, 2.2f); + #else + return color; + #endif +} + +half4 tex2D_TryLinearizeWithoutAlpha(sampler2D tex, float2 uv) +{ + #if defined(UNITY_COLORSPACE_GAMMA) + return TryLinearizeWithoutAlpha(tex2D(tex, uv)); + #else + return tex2D(tex, uv); + #endif +} + +inline float LinearToGammaSpaceExact (float value) +{ + if (value <= 0.0F) + return 0.0F; + else if (value <= 0.0031308F) + return 12.92F * value; + else if (value < 1.0F) + return 1.055F * pow(value, 0.4166667F) - 0.055F; + else + return pow(value, 0.45454545F); +} + +// real FastSRGBToLinear(real c) +// { +// return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); +// } + +// float2 Rotate_Radians_float(float2 UV, float2 Center, float Rotation) +// { +// if(Rotation == 0) +// { +// return UV; +// } +// +// // Rotation = Rotation / 180 * 3.14; //从角度转为弧度。 +// Rotation *= 0.01745329222; //从角度转为弧度。 +// UV -= Center; +// float s = sin(Rotation); +// float c = cos(Rotation); +// float2x2 rMatrix = float2x2(c, -s, s, c); +// rMatrix *= 0.5; +// rMatrix += 0.5; +// rMatrix = rMatrix * 2 - 1; +// UV.xy = mul(UV.xy, rMatrix); +// UV += Center; +// return UV; +// } + +float2 Rotate_Radians_float(float2 UV, float2 Center, float Rotation) +{ + if(Rotation == 0) + { + return UV; + } + + // Rotation = Rotation / 180 * 3.14; //从角度转为弧度。 + Rotation *= 0.01745329222; //从角度转为弧度。 + float s, c; // 如果 angle 是 uniform,每帧或每物件算一次更省 + sincos(Rotation, s, c); // HLSL 内置,一次算出 sin/cos + + float2 d = UV - Center; + // 旋转 (x', y') = ( c*x - s*y, s*x + c*y ) + float2 r = float2(dot(d, float2( c, -s)), + dot(d, float2( s, c))); + + return r + Center; +} + +inline half luminance(half3 color) +{ + return dot(color, float3(0.2126f, 0.7152f, 0.0722f)); +} + +inline half DepthFactor(float Z, float near, float far) +{ + Z = saturate((Z-near)/(far - near)); + return Z; +} + +//抽自Unity.cginc +inline half3 LinearToGammaSpace (half3 linRGB) +{ + linRGB = max(linRGB, half3(0.h, 0.h, 0.h)); + // An almost-perfect approximation from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1 + return max(1.055h * pow(linRGB, 0.416666667h) - 0.055h, 0.h); + + // Exact version, useful for debugging. + //return half3(LinearToGammaSpaceExact(linRGB.r), LinearToGammaSpaceExact(linRGB.g), LinearToGammaSpaceExact(linRGB.b)); +} + +//ASE +float2 voronoihash1( float2 p ) +{ + + p = float2( dot( p, float2( 127.1, 311.7 ) ), dot( p, float2( 269.5, 183.3 ) ) ); + return frac( sin( p ) *43758.5453); +} + +//ASE +float voronoi1( float2 v, float time, inout float2 id, inout float2 mr, float smoothness ) +{ + float2 n = floor( v ); + float2 f = frac( v ); + float F1 = 8.0; + float F2 = 8.0; float2 mg = 0; + for ( int j = -1; j <= 1; j++ ) + { + for ( int i = -1; i <= 1; i++ ) + { + float2 g = float2( i, j ); + float2 o = voronoihash1( n + g ); + o = ( sin( time + o * 6.2831 ) * 0.5 + 0.5 ); float2 r = f - g - o; + float d = 0.5 * dot( r, r ); + if( d x0.y ? float2(1, 0) : float2(0, 1); + float2 x1 = x0 + C1 - i1; + float2 x2 = x0 + C1 * 2 - 1; + + // Permutations + i = wglnoise_mod289(i); // Avoid truncation effects in permutation + float3 p = wglnoise_permute( i.y + float3(0, i1.y, 1)); + p = wglnoise_permute(p + i.x + float3(0, i1.x, 1)); + + // Gradients: 41 points uniformly over a unit circle. + // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) + float3 phi = p / 41 * 3.14159265359 * 2; + float2 g0 = float2(cos(phi.x), sin(phi.x)); + float2 g1 = float2(cos(phi.y), sin(phi.y)); + float2 g2 = float2(cos(phi.z), sin(phi.z)); + + // Compute noise and gradient at P + float3 m = float3(dot(x0, x0), dot(x1, x1), dot(x2, x2)); + float3 px = float3(dot(g0, x0), dot(g1, x1), dot(g2, x2)); + + m = max(0.5 - m, 0); + float3 m3 = m * m * m; + float3 m4 = m * m3; + + float3 temp = -8 * m3 * px; + float2 grad = m4.x * g0 + temp.x * x0 + + m4.y * g1 + temp.y * x1 + + m4.z * g2 + temp.z * x2; + + return 99.2 * float3(grad, dot(m4, px)); +} + +float SimplexNoise(float2 v) +{ + return SimplexNoiseGrad(v).z; +} + +#endif diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise2D.hlsl.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise2D.hlsl.meta new file mode 100644 index 00000000..6b1fb6c3 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise2D.hlsl.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 66b8605d5d2f14d408b0f4aee5f9d25a +timeCreated: 1498976326 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise3D.hlsl b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise3D.hlsl new file mode 100644 index 00000000..bbe90070 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise3D.hlsl @@ -0,0 +1,76 @@ +// +// Description : Array and textureless GLSL 2D/3D/4D simplex +// noise functions. +// Author : Ian McEwan, Ashima Arts. +// Maintainer : ijm +// Lastmod : 20110822 (ijm) +// License : Copyright (C) 2011 Ashima Arts. All rights reserved. +// Distributed under the MIT License. See LICENSE file. +// https://github.com/ashima/webgl-noise +// + +#ifndef _INCLUDE_JP_KEIJIRO_NOISESHADER_SIMPLEX_NOISE_3D_HLSL_ +#define _INCLUDE_JP_KEIJIRO_NOISESHADER_SIMPLEX_NOISE_3D_HLSL_ + +#include "Common.hlsl" + +float4 SimplexNoiseGrad(float3 v) +{ + // First corner + float3 i = floor(v + dot(v, 1.0 / 3)); + float3 x0 = v - i + dot(i, 1.0 / 6); + + // Other corners + float3 g = x0.yzx <= x0.xyz; + float3 l = 1 - g; + float3 i1 = min(g.xyz, l.zxy); + float3 i2 = max(g.xyz, l.zxy); + + float3 x1 = x0 - i1 + 1.0 / 6; + float3 x2 = x0 - i2 + 1.0 / 3; + float3 x3 = x0 - 0.5; + + // Permutations + i = wglnoise_mod289(i); // Avoid truncation effects in permutation + float4 p = wglnoise_permute( i.z + float4(0, i1.z, i2.z, 1)); + p = wglnoise_permute(p + i.y + float4(0, i1.y, i2.y, 1)); + p = wglnoise_permute(p + i.x + float4(0, i1.x, i2.x, 1)); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + float4 gx = lerp(-1, 1, frac(floor(p / 7) / 7)); + float4 gy = lerp(-1, 1, frac(floor(p % 7) / 7)); + float4 gz = 1 - abs(gx) - abs(gy); + + bool4 zn = gz < -0.01; + gx += zn * (gx < -0.01 ? 1 : -1); + gy += zn * (gy < -0.01 ? 1 : -1); + + float3 g0 = normalize(float3(gx.x, gy.x, gz.x)); + float3 g1 = normalize(float3(gx.y, gy.y, gz.y)); + float3 g2 = normalize(float3(gx.z, gy.z, gz.z)); + float3 g3 = normalize(float3(gx.w, gy.w, gz.w)); + + // Compute noise and gradient at P + float4 m = float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)); + float4 px = float4(dot(g0, x0), dot(g1, x1), dot(g2, x2), dot(g3, x3)); + + m = max(0.5 - m, 0); + float4 m3 = m * m * m; + float4 m4 = m * m3; + + float4 temp = -8 * m3 * px; + float3 grad = m4.x * g0 + temp.x * x0 + + m4.y * g1 + temp.y * x1 + + m4.z * g2 + temp.z * x2 + + m4.w * g3 + temp.w * x3; + + return 107 * float4(grad, dot(m4, px)); +} + +float SimplexNoise(float3 v) +{ + return SimplexNoiseGrad(v).w; +} + +#endif diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise3D.hlsl.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise3D.hlsl.meta new file mode 100644 index 00000000..48962bca --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/Shader/SimplexNoise3D.hlsl.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2b1bb9b67aabb824998a7d2e026d2606 +timeCreated: 1498976326 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/package.json b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/package.json new file mode 100644 index 00000000..a57b1f83 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/package.json @@ -0,0 +1,13 @@ +{ + "author": "Keijiro Takahashi", + "description": "Noise Shader provides lightweight 2D/3D gradient noise functions for shader use.", + "displayName": "Noise Shader", + "keywords": [ "unity" ], + "license": "MIT", + "name": "jp.keijiro.noiseshader", + "repository": "github:keijiro/NoiseShader", + "unity": "2019.3", + "unityRelease": "0f1", + "version": "2.0.0" +} + diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/package.json.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/package.json.meta new file mode 100644 index 00000000..168c6744 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/jp.keijiro.noiseshader/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 39ccfaa9af9f4dc84a876b1b1c3ae8bb +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/StencilConfig.asset b/Packages/NB_FX/XuanXuanRenderUtility/Shader/StencilConfig.asset new file mode 100644 index 00000000..278c5b6c --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/StencilConfig.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6aa85c127490f523ac3a3d65dce36f78f1e90fec271404df27af3b38dbdaa089 +size 1607 diff --git a/Packages/NB_FX/XuanXuanRenderUtility/Shader/StencilConfig.asset.meta b/Packages/NB_FX/XuanXuanRenderUtility/Shader/StencilConfig.asset.meta new file mode 100644 index 00000000..fbd9e6e5 --- /dev/null +++ b/Packages/NB_FX/XuanXuanRenderUtility/Shader/StencilConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d7093501998f1b24483fa6c8eddcf8fb +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/NB_FX/package.json b/Packages/NB_FX/package.json new file mode 100644 index 00000000..70b7f9d9 --- /dev/null +++ b/Packages/NB_FX/package.json @@ -0,0 +1,7 @@ +{ + "name": "com.xuanxuan.nb.fx", + "version": "2.0.0", + "displayName": "NB_FX", + "description": "NB特效框架", + "unity": "2021.1" +} \ No newline at end of file diff --git a/Packages/NB_FX/package.json.meta b/Packages/NB_FX/package.json.meta new file mode 100644 index 00000000..c71a0b14 --- /dev/null +++ b/Packages/NB_FX/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e9e4b9cfaabda4f4296d2f1a28bc3501 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: