SchultzGames
Para tirar dúvidas, crie um tópico especifico na área "Dúvidas em Geral" e aguarde ser respondido. Evite comentar em tópicos não relacionados a sua dúvida :D
TÓPICOS RECENTES:
Tópico:
Postado em:
Postado por:
Simulador de Controle de Tráfego Aéreo
Tenho um jogo disponivel na steam
Erro unity - textMeshPro
Pulo Na Unity projeto 3d
Transição de cenas
Como funciona o " sistema base" do game?
R$: Orçamento para um jogo 2D
Alguém manja de iluminação na unity?
Armadilha do Super Meat Boy
Tiro continuar em linha reta depois de chegar ao "alvo"
Toogle, é possível carregar estado de um PlayerPrefs?
Jogo de Terror em Desenvolvimento, preciso de programador.
Problema do Animator Unity3D
UNITY REMOTE NÃO FUNCIONA O QUE FAZER?
Como pego um valor exato da rotação no transform?
[TUTORIAL] Shader de renderização baseada em física
Carregar personagem + scripts na nova cena
Itens coletados reaparecem na cena ao retornar para a fase
Como fazer player ir do chão pro teto e do teto pro chão (2D game)
[TUTORIAL] Sistema de tiro com RAYCAST (várias armas, mira laser, munição, dano, etc, etc)
Queria ajuda para fazer um sistema de rastro no personagen
[TUTORIAL] Fazer objeto se mover em pontos diferentes (Serve para 2D e 3D).
Qual a melhor forma de fazer um efeito parecido com um launchpad[UNITY]?
dúvida para fazer sistema de som de passos em terreno
Movimentação de BoardGame
Produção de um Roteiro - Arquétipos.
Como gerenciar o Sorting Layer de varios objetos em cena
Como colocar um boneco pra andar pelo mapa?
Não tá dando mais Bake. O que pode ser?Não aparece mais as áreas em azul em
Como fazer um corredor ''infinito'' na unity?
Livro de Unity2D
Como posso saber quanto de memória o meu projeto está pesando?
Boas E velhas sombras alguem resolve??
Qual seria a maneira correta de fazer a rotação de um obj
Importar arquivos externo para dentro do unity em tempo de execução
Layouts de interface para Unity3D
Erro no meu jogo de plataforma 2D
Rapper Simulator (demo) mobile
Reduzir tamanho da textura
Unity + Photon 2
Game view incorreto
DUVIDA DO SISTEMA DE CORPO A CORPO
Erro no WebGl
Jogo 2D Multiplayer é trabalhoso?
Sistema completo de FPS, (by u/KFriske)
Preciso De Um Programador! Para Um Game Fps!
MOD MINECRAFT JAVA (Formação de Equipe).
2 Artistas procuram Programador experiente em UNITY 2D
OPORTUNIDADE DE FREELANCE
Busco alguem pra fazer algumas programações basicas (PAGO EM DINHEIRO)
[TUTORIAL] MENU PRINCIPAL - UNITY 5 (5.3 ou superior) (Com UI)
Alguém precisando de um artists pixel?
[TUTORIAL] Unity 2019.4 ou superior - PRESETS
[RESOLVIDO] Unity - Dúvida
A unity não abre o projeto!!
[Dúvida] Script retorna erro apenas quando não esta selecionado
[RESOLVIDO] Jogo 2D unity - trocar sprite ao apertar botão
WaitForSeconds não funciona
ToString(); não funciona
o meu terrain ficou branco como poss resolver?
Lançar Granada
Criação de um jogo de sobrevivência
[ASSET] UDost Jump Projeto
[TUTORIAL] Lanterna
[TUTORIAL] Sistema de Grappling Hook / Corda e Gancho
Não consigo interagir com o objeto no app
[RESOLVIDO] Criar textura com fundo transparente
Meu Projeto mobile 2D (RYB 2DASH)
como fazer meu personagem correr sozinho?
[_____CRONOGRAMA DO CANAL_____]
[ASSET] Script Arma Completo Incluso Recuo. Incluso outros Scripts
[RESOLVIDO] ALGUEM ME AJUDA COM A MUSICA NA UNITY
Por que a rotação do Box Collider não está certa?
Caminhar do inimigo!!
[RESOLVIDO] Animação não funciona - Unity 3D
Contratação de freelancer em programação para unity
build settings parou de funcionar!!!
[TUTORIAL] Sistema de fome, sede, barra de vida, barra de estamina, itens e dano por queda
Como acelerar uma uma animação por script?
Jogo se conectando ao play games toda vez que inicia o menu.
procuro modeladores e artista para projeto de Moba
Criar tutorial antes do jogo
Parallax no Menu
[TUTORIAL] Como fazer um TELEPORTE
[Dúvida] comunicação de multiplas linguagens c/ o xml/json desempenho
Ajuda com INT
[RESOLVIDO] Clicar em um botão e o personagem se mover por uma distância.
Script de pegar um item/coletável pressionando a tecla ''E''
alterar Transform via script
Como usar um personagem low poly como personagem jogavel
Loja de roupa para personagem 2D
Fazer imagem piscar uma vez depois de um determinado tempo
O QUE FAZER PARA O PERSONAGEM DETECTAR O TERRAIN ?
[RESOLVIDO] Não acho o fps controller da unity
SOU MODELADOR SE TIVER ALGUEM PRECISANDO AI ME CONTATE
Projeto Quiz Ajuda
Outline 2d em cena 3d
é possivel criar uma animação para multiplos objetos?
Como induzir o jogador a pressionar um botão no tempo certo ?
Hoje à(s) 2:11 pm
Hoje à(s) 1:17 pm
Hoje à(s) 12:01 pm
Hoje à(s) 10:33 am
Ontem à(s) 9:09 pm
Ontem à(s) 9:01 pm
Ontem à(s) 3:34 pm
Ontem à(s) 2:22 pm
Ontem à(s) 1:51 pm
Dom Out 18, 2020 11:33 pm
Dom Out 18, 2020 9:54 pm
Dom Out 18, 2020 8:52 pm
Dom Out 18, 2020 8:02 pm
Dom Out 18, 2020 3:19 pm
Dom Out 18, 2020 1:26 pm
Dom Out 18, 2020 1:17 am
Sab Out 17, 2020 10:37 pm
Sab Out 17, 2020 10:01 pm
Sab Out 17, 2020 9:46 pm
Sab Out 17, 2020 8:56 pm
Sex Out 16, 2020 10:24 pm
Sex Out 16, 2020 9:56 pm
Sex Out 16, 2020 8:54 pm
Sex Out 16, 2020 1:24 pm
Sex Out 16, 2020 11:41 am
Sex Out 16, 2020 11:08 am
Sex Out 16, 2020 2:48 am
Qui Out 15, 2020 11:45 pm
Qui Out 15, 2020 9:58 pm
Qui Out 15, 2020 2:55 pm
Qui Out 15, 2020 2:49 pm
Qui Out 15, 2020 12:56 pm
Qui Out 15, 2020 10:32 am
Qui Out 15, 2020 4:20 am
Qui Out 15, 2020 12:00 am
Qua Out 14, 2020 11:42 pm
Qua Out 14, 2020 10:03 pm
Qua Out 14, 2020 9:29 pm
Qua Out 14, 2020 7:34 pm
Qua Out 14, 2020 7:31 pm
Qua Out 14, 2020 7:25 pm
Qua Out 14, 2020 7:15 pm
Qua Out 14, 2020 7:09 pm
Ter Out 13, 2020 11:15 pm
Ter Out 13, 2020 7:14 pm
Ter Out 13, 2020 1:58 pm
Ter Out 13, 2020 1:55 pm
Ter Out 13, 2020 1:53 pm
Ter Out 13, 2020 1:52 pm
Ter Out 13, 2020 1:51 pm
Ter Out 13, 2020 11:37 am
Ter Out 13, 2020 1:07 am
Seg Out 12, 2020 10:47 am
Dom Out 11, 2020 10:52 pm
Dom Out 11, 2020 7:53 pm
Dom Out 11, 2020 7:50 pm
Dom Out 11, 2020 7:45 pm
Dom Out 11, 2020 7:21 pm
Dom Out 11, 2020 4:26 pm
Dom Out 11, 2020 8:07 am
Sab Out 10, 2020 11:10 am
Sex Out 09, 2020 9:18 pm
Sex Out 09, 2020 3:42 pm
Sex Out 09, 2020 2:21 pm
Sex Out 09, 2020 1:10 pm
Sex Out 09, 2020 11:39 am
Sex Out 09, 2020 2:06 am
Qui Out 08, 2020 8:21 pm
Qui Out 08, 2020 5:14 pm
Qui Out 08, 2020 5:07 pm
Qui Out 08, 2020 10:33 am
Qua Out 07, 2020 4:50 pm
Qua Out 07, 2020 8:48 am
Seg Out 05, 2020 10:19 pm
Seg Out 05, 2020 10:13 am
Seg Out 05, 2020 10:00 am
Seg Out 05, 2020 6:52 am
Seg Out 05, 2020 5:09 am
Dom Out 04, 2020 9:35 pm
Dom Out 04, 2020 6:23 pm
Dom Out 04, 2020 4:13 pm
Dom Out 04, 2020 12:37 am
Dom Out 04, 2020 12:35 am
Dom Out 04, 2020 12:29 am
Dom Out 04, 2020 12:27 am
Sab Out 03, 2020 11:54 pm
Sab Out 03, 2020 8:15 am
Sex Out 02, 2020 7:08 pm
Sex Out 02, 2020 5:33 pm
Sex Out 02, 2020 3:43 pm
Sex Out 02, 2020 2:30 pm
Sex Out 02, 2020 2:18 pm
Sex Out 02, 2020 1:02 pm
Qui Out 01, 2020 4:35 pm
Qui Out 01, 2020 1:26 pm
Qui Out 01, 2020 1:06 pm
Qui Out 01, 2020 12:34 pm
Qui Out 01, 2020 10:27 am
Qui Out 01, 2020 9:53 am
joz
diegopds
orph
FelipeSouza11
Micco
Micco
Ki
glauco
Wily
Shidote
MarcosSchultz
thales.ulisses
darkrj
NKKF
Liherbert
NKKF
TDM Corp
Fagner
nvndx
TDM Corp
Arturzeraa
ecorrea
TioUV
Franttyck
Fagner
cosmoplay
drewhonshu
leandrabr
RodrigoPrivilegium
cafezinho71
leandrabr
glauco
rondon2014
Fagner
Evertonslv
Evertonslv
El Marquitoos
Callyde Jr
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
Markimg22
leandrabr
Ki
Ki
Ki
Ki
Ki
ViniciusTKH
Pancakemix
MarcosSchultz
Hiyuzo
MarcosSchultz
MarcosSchultz
deathmasterxz
MarcosSchultz
NKKF
LUCASkkk
marx478
PacienteZERO
FelipeSouza11
Toxic
cafezinho71
NKKF
Evertonslv
TioUV
MarcosSchultz
MarcosSchultz
cafezinho71
SauloeArthur
glauco
Callyde Jr
PedrinHFS
orph
SauloeArthur
cafezinho71
JulioWinchester
pratesgamedev
Valakinhas
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
Markimg22
AmazingDeliciano
Fagner
Fagner
Markimg22
Markimg22
Markimg22
BatataBugada54321
Chilinger
Chilinger
Th2y
PauloFR
PauloFR

[TUTORIAL] Shader de renderização baseada em física

Ir em baixo

TUTORIAL [TUTORIAL] Shader de renderização baseada em física

Mensagem por Matrirxp em Sex Out 16, 2020 11:39 pm

Bom dia! Boa tarde! Boa Noite!
Hoje venho trazer um tutorial de HLSL para shader PBR na unity.

[TUTORIAL] Shader de renderização baseada em física IlRe0Vk

E recomendado que você saiba o pelo menos básico de shader e hlsl, já que nesse tutorial não será abordado a criação de shaders.
Eu vou usar uma API própria + Render Pipelines Core para o shader, já que estou usando um SRP (Scriptable Render Pipeline), isso facilita no uso de Global Illumination, nas conversões de espaço, etc.

[TUTORIAL] Shader de renderização baseada em física XxsZQyv
Mas você pode fazer isso com as ferramentas padrões da unity, porem vai dar um pouco mais de trabalho.
Dito isso vamos começar!

Estrutura Base do shader:

Criei 2 arquivos para deixar mais organizado.
O primeiro e o Shader. (Arquivo .shader)
O segundo serão nossos Pass [Pixel Shader e Vertex Shader]. (Arquivo .hlsl)

[TUTORIAL] Shader de renderização baseada em física KA0AAVN
[TUTORIAL] Shader de renderização baseada em física JLnQSuO

PBR.shader

Código:
Shader "Magic Byte/Standard PBR" {
 
 Properties {

 /*Blend options*/
 [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend", Float) = 1 //One
 [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend", Float) = 0 //Zero
 [Enum(Off, 0, On, 1)] _ZWrite ("Z Write", Float) = 1 //On
 /*Blend options*/

 [HideInInspector] _MainTex("Lightmap Texture", 2D) = "white" {} // Uso de GI em SRP (Retrire essas propriedades)
 [HideInInspector] _Color("Lightmap Color", Color) = (0.5, 0.5, 0.5, 1.0) // Uso de GI em SRP (Retrire essas propriedades)
 }
 
 SubShader {
 HLSLINCLUDE
 #include "../../ShaderLibrary/Common.hlsl" //API de graficos da MB (Retire esse include)
 ENDHLSL

 Pass {
 Tags {
 "LightMode" = "MBLit"
 }

 /*Blend*/
 Blend [_SrcBlend] [_DstBlend]
 ZWrite [_ZWrite]
 /*Blend*/

 HLSLPROGRAM
 /*Features para SRP*/
 #pragma target 3.5
 #pragma shader_feature _CLIPPING
 #pragma shader_feature _RECEIVE_SHADOWS
 #pragma shader_feature _PREMULTIPLY_ALPHA
 #pragma multi_compile _ LOD_FADE_CROSSFADE
 #pragma multi_compile _ _DIRECTIONAL_PCF3 _DIRECTIONAL_PCF5 _DIRECTIONAL_PCF7
 #pragma multi_compile _ _CASCADE_BLEND_SOFT _CASCADE_BLEND_DITHER
 #pragma multi_compile _ _SHADOW_MASK_ALWAYS _SHADOW_MASK_DISTANCE 
 #pragma multi_compile _ LIGHTMAP_ON
 #pragma multi_compile _ DYNAMICLIGHTMAP_ON
 #pragma multi_compile_instancing
 /*Features para SRP*/

 #pragma vertex PBRPassVertex // <-- VERTEX SHADER
 #pragma fragment PBRPassFragment // <-- PIXEL SHADER
 #include "PBRPass.hlsl" // <-- Incluir Arquivo com os Pass
 ENDHLSL
 }

 }
}

PBRPass.hlsl

Código:
#ifndef PBR_PASS_INCLUDED
#define PBR_PASS_INCLUDED

/* API GRAFICA MB */
#include "../../ShaderLibrary/Surface.hlsl"
#include "../../ShaderLibrary/Shadows.hlsl"
#include "../../ShaderLibrary/Light.hlsl"
#include "../../ShaderLibrary/BRDF.hlsl"
#include "../../ShaderLibrary/GI.hlsl"
#include "../../ShaderLibrary/Lighting.hlsl"
#include "../../ShaderLibrary/ClearCoat.hlsl"
/* API GRAFICA MB */

struct Attributes {
 float3 positionOS : POSITION;
 float3 normalOS : NORMAL;
 float4 tangentOS : TANGENT;
 float2 baseUV : TEXCOORD0;
 float2 lightmapUV: TEXCOORD1;
 float2 dynamicLightmapUV : TEXCOORD2;
 UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct Varyings {
 float4 positionCS : SV_POSITION;
 float3 positionWS : VAR_POSITION;
 float3 normalWS : VAR_NORMAL;
 float4 tangentWS : VAR_TANGENT;
 float2 baseUV : VAR_BASE_UV;
 float2 lightmapUV : TEXCOORD4;
 float2 dynamicLightmapUV : TEXCOORD5;
 UNITY_VERTEX_INPUT_INSTANCE_ID
};

Varyings PBRPassVertex (Attributes input) {
 Varyings output;

 /* API GRAFICA MB */
 output.lightmapUV = input.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;
 output.dynamicLightmapUV = input.dynamicLightmapUV * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
 /* API GRAFICA MB */

 /* Render Pipelines Core */
 output.positionWS = TransformObjectToWorld(input.positionOS); // MULTIPLICACOES DE MATRIZES PARA A CONVERSAO DE ESPACO
 output.positionCS = TransformWorldToHClip(output.positionWS);
 output.normalWS = TransformObjectToWorldNormal(input.normalOS);
 output.tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
 output.baseUV = input.baseUV;
 /* Render Pipelines Core */

 return output;
}
float4 _Time; //Funcao tempo importada da unity por buffer
float4 PBRPassFragment(Varyings input) : SV_TARGET{
 float3 color = (0,0,0);



 return float4(color,1);
}

#endif

Definições de propriedades:
Antes de começarmos o PBR vamos definir as propriedades do nosso shader.


PBR.shader

Código:
Properties {

 _BaseMap("Texture", 2D) = "white" {} //Mapa de textura
 _BaseColor("Color", Color) = (0.5, 0.5, 0.5, 1.0) //Cor de material

 _Metallic("Metallic", Range(0, 1)) = 0 //Nivel metalico (0,1)
 _Smoothness("Smoothness", Range(0, 1)) = 0.5 //Nivel de "superficie aspera" ou nivel de suavidade
 _Occlusion("Occlusion", Range(0, 1)) = 1 //Nivel de microsombras do mapa de oclusao

 [NoScaleOffset] _OcclusionMap("Occlusion Map(AO)", 2D) = "white" {} //Mapa de Oclusao

 [NoScaleOffset] _SmoothnessMap("Smoothness Map(Specular)", 2D) = "white" {} //Mapa de nivel de suavidade
 [NoScaleOffset] _MetalMap("Metallic Map", 2D) = "white" {} //Mapa de nivel metalico

 [NoScaleOffset] _EmissionMap("Emission", 2D) = "white" {} //Mapa de emissao
 [HDR] _EmissionColor("Emission", Color) = (0.0, 0.0, 0.0, 0.0) //Cor da emissao

 [NoScaleOffset] _NormalMap("Normals", 2D) = "bump" {} //Mapa normal
 _NormalStrength("Normal Strength", Range(0, 1)) = 1 //Nivel de mapa normal
 
    _Fresnel("Reflectance", Range(0,3)) = 0.0 //Reflectancia do material. (0,3) Para fins artisticos

}

No arquivo "PBRPass.hlsl" vamos definir uma struct para armazenar as propriedades do nosso material (superficie).

PBRPass.hsls

Código:
struct Surface {
 float3 position; //Posicao no espaco de mundo
 float3 normal; //Vetor Normal
 float3 interpolatedNormal; //Normal de espaco de mundo
 float3 viewDirection; //Direcao de visao
 float4 tangent; //Vetor de tangentes de superficie
 float3 binormal; //Vetor de binormal Produto cruzado -- > cross(vetor normal, vetor tangente) * vetor tangente
 float3 color; //Cor da superficie
 float alpha; //Nivel de transparencia
 float metallic; //Nivel Metalico
 float smoothness; //Nivel de suavidade
 float occlusion; //Nivel de oclusao
 float fresnelStrength; //Nivel de reflectancia
};

Agora vamos adicionar os valores dessas propriedades no nosso struct de superficie:

PBRPass.hlsl

Código:
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);

TEXTURE2D(_NormalMap);
SAMPLER(sampler_NormalMap);

TEXTURE2D(_OcclusionMap);
SAMPLER(sampler_OcclusionMap);

TEXTURE2D(_SmoothnessMap);
SAMPLER(sampler_SmoothnessMap);

TEXTURE2D(_MetalMap);
SAMPLER(sampler_MetalMap);

TEXTURE2D(_EmissionMap);
SAMPLER(sampler_EmissionMap);

float4 _BaseColor;
float _NormalStrength;
float _Metallic;
float _Smoothness;
float _Occlusion;
float4 _EmissionColor;
float _Fresnel;

float4 PBRPassFragment(Varyings input) : SV_TARGET{
 float3 color = (0,0,0);

 Surface surface;
 surface.position = input.positionWS;

 float4 Nmap = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.baseUV);
 float3 normal = DecodeNormal(Nmap, _NormalStrength);

 surface.normal = NormalTangentToWorld(normal, input.normalWS, input.tangentWS); // <---- Transformacao de espaco do Render Pipelines Core
 surface.interpolatedNormal = input.normalWS;
 surface.viewDirection = normalize(_WorldSpaceCameraPos - input.positionWS); //Normalizar posicao da camera - posicao de objeto
 surface.tangent = input.tangentWS;
 surface.binormal = cross(NormalTangentToWorld(normal, input.normalWS, input.tangentWS), input.tangentWS.xyz) * input.tangentWS.w;
 surface.color = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.baseUV) * _BaseColor.rgb;
 surface.alpha = _BaseColor.a;

 float metallic = _Metallic;
 metallic *= pow(abs(SAMPLE_TEXTURE2D(_MetalMap, sampler_MetalMap, input.baseUV).r), 2.2); //Correcao de Gamma do mapa (Fins artisticos)

 float smoothness = _Smoothness;
 smoothness *= pow(abs(SAMPLE_TEXTURE2D(_SmoothnessMap, sampler_SmoothnessMap, input.baseUV).r), 2.2); //Correcao de Gamma do mapa (Fins artisticos)
 //Usamos o nivel de red da textura para definir o nivel de smootheness a partir de uma mascara de smoothness, o mesmo e feito com a mascara(mapa) de metal e de oclusao
 
 float occlusion = _Occlusion;
 occlusion *= pow(abs(SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, input.baseUV).r), 2.2); //Correcao de Gamma do mapa (Fins artisticos)

 surface.metallic = metallic;
 surface.smoothness = smoothness;
 surface.occlusion = occlusion;

 surface.fresnelStrength = _Fresnel;

 color += SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, input.baseUV) * _EmissionColor;

 return float4(color, surface.alpha);
}


Iluminação Bruta

Como dito acima, estou utilizando um SRP, logo toda a iluminação do meu objeto tem que ser feita por mim. Por esse motivo, o próximo tópico mostra como a iluminação bruta do objeto foi gerada.
Esse tópico serve apenas para mostrar com mais clareza como a luz esta sendo gerada nesse shader, por isso, pode ser ignorado no caso de você estar fazendo um shader com a iluminação da unity.

Por enquanto nosso shader está todo preto, isso acontece pois a única cor adicionada é a emissão.


[TUTORIAL] Shader de renderização baseada em física CifZyGD


Então precisamos adicionar a luz da Directional Light, faremos isso a partir dos dados que o pipeline está mandando para a GPU.


[TUTORIAL] Shader de renderização baseada em física 5DAiAmg
c#

Vamos criar uma função para tratar a iluminação de cada Directional Light e também dar suporte a Iluminação Global no PBRPass.
A iluminação bruta será calculada a partir do produto escalar (cosseno) entre o vetor normal e o vetor de direção da luz vezes a atenuação da luz (definida individualmente em cada luz). Depois disso, multiplicamos pela cor da luz, assim as partes escuras permanecem escuras (pois na escala de cor o preto e igual a 0), a as partes claras ganham cor.

Função Dot:


[TUTORIAL] Shader de renderização baseada em física BWRo7yQ

PBRPass.hlsl

Código:
float3 Lighting(Surface surface, GI gi) {
 ShadowData shadowData = GetShadowData(surface);//Preparar GI
 shadowData.shadowMask = gi.shadowMask;

 float3 color = (0, 0, 0);
 for (int i = 0; i < GetDirectionalLightCount(); i++) {
 Light light = GetDirectionalLight(i, surface, shadowData);//Compilar Luz
 color += saturate(dot(surface.normal, light.direction) * light.attenuation) * light.color;//Adicionar sombra propria
 }
 return color;
}

Feito isso, já podemos adicionar a iluminação na cor final do pixel shader:
Código:
GI gi = GetGI(input.lightmapUV, input.dynamicLightmapUV, surface,  (1 - surface.smoothness), 1);
 color = Lighting(surface, gi);

Agora já temos nossa primeira iluminação:
[TUTORIAL] Shader de renderização baseada em física Xbfg2FV

Oque é PBR:

PBR ou Physically based rendering (Renderização baseada em física) são técnicas de renderização que tem como objetivo simular aproximações físicas do mundo real na iluminação gerada em computador
Para que um modelo de iluminação seja considerado fisicamente baseado ele deve seguir 3 condições básicas.

1- Conservar sua energia
2- Simulação de microfacetes
3- Modelo de BRDF fisicamente baseado

Nesse tutorial o modelo adotado será um modelo usado na Magic Byte RP parecido com o modelo de BRDF da Disney, que aborda um estilo mais artístico do que físico.

Simulação de Microfacetes:

A teoria de microfacetes nos mostra que todo superfície em uma escala microscópica possui pequenas ranhuras com funcionam como espelhos perfeitamente reflexivos. Em algumas superfícies chamadas de dielétricas, essas ranhuras não são alinhas espalhando a luz de forma aleatória, assim mantendo uma iluminacao difusa.
Já as superfícies metílicas espelham a luz de forma uniforme, criando um brilho especular.

[TUTORIAL] Shader de renderização baseada em física Pz59Iif
[TUTORIAL] Shader de renderização baseada em física TzuDL3H[TUTORIAL] Shader de renderização baseada em física 8FgWji6
Dielétrica / Metálica
[TUTORIAL] Shader de renderização baseada em física YvA2k0c


Em resumo, quando mais áspera for a superfície, mais desalinhado as microfissuras estarão.

Modelo de microfacetes:
[TUTORIAL] Shader de renderização baseada em física D9uOj4K
G(n,l,v): Termo geometrico (Modelo usado Smith)
F(n,v): Termo Fresnel (Modelo usado Schlick)


Calcular BRDF

Primeiro temos que criar uma estrutura para armazenar os dados do BRDF, assim como fizemos para a superfície.

PBRPass.hlsl

Código:
struct BRDF{
 float3 diffuse;
 float3 specular;
 float perceptualRoughness;
 float roughness;
};

Agora vamos criar uma função para tratar os dados do BRDF.

Código:
BRDF GetBRDF(Surface surface) {
 BRDF brdf;

 brdf.diffuse = surface.color * (1 - surface.metallic);
 brdf.specular = lerp(0, surface.color, surface.metallic);

 brdf.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surface.smoothness);
 brdf.roughness = PerceptualRoughnessToRoughness(brdf.perceptualRoughness);

 return brdf;
}

E uma função para retornar a simulação de microfacetes (Chamaremos de Iluminação direta).

Código:
float3 DirectIllumination(Surface surface, BRDF brdf, Light light) {
 
 return brdf.diffuse;

}


Agora vamos adicionar a iluminação direta na nossa função de iluminação bruta

Código:
float3 Lighting(Surface surface, GI gi) {
 ShadowData shadowData = GetShadowData(surface);
 shadowData.shadowMask = gi.shadowMask;

 BRDF brdf = GetBRDF(surface);

 float3 color = (0,0,0);
 for (int i = 0; i < GetDirectionalLightCount(); i++) {
 Light light = GetDirectionalLight(i, surface, shadowData);//Compilar Luz
 color += dot(surface.normal, light.direction) * light.attenuation * light.color * DirectIllumination(surface, brdf, light);//Adicionar sombra propria
 }
 return color;
}


Com isso já estamos prontos para começar as simulações. 
No entanto, quando tentamos usar um material quase 100% metálico o resultado é uma parte difusa completamente preta, oque para fins fisicos não e interessante.
[TUTORIAL] Shader de renderização baseada em física KL8xEqv

Temos que criar uma função que limite o nível metálico em 0.04 (Nível mínimo definido pela Unity na URP).

Código:
#define MIN_REFLECTIVITY 0.04 // <--Nivel minimo

float OneMinReflectivity(float metallic) {
 float size = 1.0 - MIN_REFLECTIVITY; // <-- Inverter nivel (One Minus)
 return size - metallic * size; // <-- Para pequenos niveis retornar inverso da reflexão minima
}

BRDFGetBRDF(Surface surface) {
 BRDF brdf;

 brdf.diffuse = surface.color * OneMinReflectivity(surface.metallic); //<-- Brilho difuso (com base no nivel metalico)
 brdf.specular = lerp(MIN_REFLECTIVITY, surface.color, surface.metallic);

 brdf.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surface.smoothness);
 brdf.roughness = PerceptualRoughnessToRoughness(brdf.perceptualRoughness);

 return brdf;
}


Função de Distribuição

Para calcular a termo D vamos usar a função GGX, que utiliza o produto escalar entre vetor mediano, entre o vetor de direção da luz e o vetor normal, e o vetor normal.
[TUTORIAL] Shader de renderização baseada em física 9Tqx41r
[TUTORIAL] Shader de renderização baseada em física ZqrYkld

NxH = produto cruzado entre o vetor Normal e o vetor Mediano
[TUTORIAL] Shader de renderização baseada em física 3RSLl1n

Nosso hlsl vai ficar assim:

Código:
//GGX
float GGX(Surface surface, BRDF brdf, Light light) {
 float3 h = SafeNormalize(light.direction + surface.viewDirection); //Half Vector (Vetor Mediano)
 float NoH = dot(surface.normal, h); //Produto escalar entre vetor normal e vetor mediano
 float3 NxH = cross(surface.normal, h);//Produto cruzado entre vetor normal e vetor mediano
 float a = NoH * brdf.roughness;
 float k = brdf.roughness / (dot(NxH, NxH) + a * a);
 float d = k * k * (1.0 / PI);//  1/PI <-- Essa e a funcao lambertiana | A divisão por pi existe para normalizar a luz
 return d;
}

float3 DirectIllumination(Surface surface, BRDF brdf, Light light) {
 
 return GGX(surface, brdf, light) + brdf.diffuse;

}

[TUTORIAL] Shader de renderização baseada em física LpbPDsK
Já temos nosso brilho especular definido.

Termo de Geometria

Para calcular o quanto um microfacete é bloqueado por outro nos usamos o Termo G ou termo de geometria, assim conseguimos calcular a influencia de um microfacete na iluminação do objeto.
No entanto, esse termo é caro em relação a processamento e seu beneficio é pequeno. Por isso, ele não será usado nesse tutorial.
Mas segue métodos de implementação para interessados:
[TUTORIAL] Shader de renderização baseada em física 3I2uNZz

Código:
 float Rough2Max = max(brdf.roughness * brdf.roughness, 2.0e-3);
 float k = Rough2Max * 0.5f;
 float GSmithL = NoL * (1.0f - k) + k;
 float GSmithV = dot(surface.normal, surface.viewDirection) * (1.0f - k) + k;
 float G = 0.25f / (GSmithL * GSmithV);



Termo Fresnel


Esse termo será responsável pela distribuição da luz em torno do material de acorda com o nível metálico.

[TUTORIAL] Shader de renderização baseada em física EQw8KA5
f0 = Nível refletância especular a 0 graus

Vamos criar uma função para processar os dados do fresnel

Código:
float FresnelSchlick(Surface surface) {
 float NoV = dot(surface.normal, surface.viewDirection);
 float f0 = pow(1.0 - NoV, 4.0);//Potencia da 4 grau no inverso (OneMinus) do produto escalar
 return f0 + NoV * (1.0 - f0) * surface.metallic;
}

Por fim, nosso função de Iluminacao direta fica assim:
Código:
float3 DirectIllumination(Surface surface, BRDF brdf, Light light) {

 return GGX(surface, brdf, light) * FresnelSchlick(surface) + brdf.diffuse;

}

[TUTORIAL] Shader de renderização baseada em física DA2eTic


Iluminação Indireta
Mais uma parte do tutorial onde a leitura é opcional, asse parte serve para adicionar a iluminação indireta da Iluminação Global ao shader, já que, estou utilizando uma SRP.

Criei uma função para processar as informações vindas do arquivo de GI.

Código:
float3 IndirectIllumination(Surface surface, BRDF brdf, float3 diffuse, float3 specular) {

 float3 reflection = specular * lerp(brdf.specular, brdf.fresnel, FresnelBRDF(surface));
 reflection /= brdf.roughness * brdf.roughness + 1.0;

 return (diffuse * (brdf.diffuse / PI) + reflection) * surface.occlusion;
}


Adicionando luz indireta na iluminacao bruta:

Código:
float3 Lighting(Surface surface, GI gi) {
 ShadowData shadowData = GetShadowData(surface);
 shadowData.shadowMask = gi.shadowMask;

 BRDF brdf = GetBRDF(surface);

 float3 color = IndirectIllumination(surface, brdf, gi.diffuse, gi.specular);
 for (int i = 0; i < GetDirectionalLightCount(); i++) {
 Light light = GetDirectionalLight(i, surface, shadowData);//Compilar Luz
 color += dot(surface.normal, light.direction) * light.attenuation * light.color * DirectIllumination(surface, brdf, light);//Adicionar sombra propria
 }
 return color;
}

[TUTORIAL] Shader de renderização baseada em física RUezSho


Conservação de Energia


A conservação de energia é um dos principais componentes de um bom BRDF, ele serve para manter os níveis de luz refletida menor do que os níveis de luz que incide no material.  
Deixando assim a termodinâmica bem feliz.


Vamos adicionar uma equação simples de conservação de energia ao nosso shader PBR.

Código:
float3 DirectIllumination(Surface surface, BRDF brdf, Light light) {

 float NoL = dot(surface.normal, light.direction);//Produto escalar entre o vetor Normal e o vetor de direcao da luz
 float3 energyCompensation = 1.0 + NoL * (1.0 / (1.1 - brdf.roughness) - 1.0); // <----

 return GGX(surface, brdf, light) * FresnelSchlick(surface) * energyCompensation + brdf.diffuse;

}

Resultado:
[TUTORIAL] Shader de renderização baseada em física L6saPVx



Nível Difuso da Disney


[TUTORIAL] Shader de renderização baseada em física Gt1JwIV
Sem Nivel Difuso da Disney

A disney usa métodos diferentes para determinar a cor difusa de um material, oque funciona muito bem para matérias metálicos, mas não tão bem para os dielétricos.
Por isso, vamos criar uma propriedade para controlar o uso dessa função.

PBR.shader



Código:
[Enum(Off, 0, On, 1)] _DisneyDiffuse("Disney Diffuse", Float) = 1 //On

Agora no arquivo PBRPass.hlsl, vamos criar a função e adicionar uma variável para essa propriedade:

PBRPass.hlsl

Código:
float _DisneyDiffuse;

Esse função requer um fresnel de Schlick próprio para transmissão de energia, então vamos coloca-lo tambem:

Código:
float FresnelTransmission(float f0, float f90, float u)
{
 real x = 1.0 - u;
 real x2 = x * x;
 real x5 = x * x2 * x2;
 return (1.0 - f90 * x5) - f0 * (1.0 - x5);
}

Código:
float disneyDiffuse(float NoV, float NoL, float LoH, float roughness)
{
 float  energyBias = lerp(0, 0.7, roughness);
 float  energyFactor = lerp(1.0, 1.0 / 1.51, roughness);
 float  fd90 = energyBias + 1.0 * LoH * LoH * roughness;
 float f0 = 1.0f;
 float lightScatter = FresnelTransmission(f0, fd90, NoL);//Controle de transmissao de energia
 float viewScatter = FresnelTransmission(f0, fd90, NoV);
 return  lightScatter * viewScatter * energyFactor;
}


Implementação:
Código:
float3 DirectIllumination(Surface surface, BRDF brdf, Light light) {

 float NoL = dot(surface.normal, light.direction);//Produto escalar entre o vetor Normal e o vetor de direcao da luz
 float3 energyCompensation = 1.0 + NoL * (1.0 / (1.1 - brdf.roughness) - 1.0);

 float3 h = SafeNormalize(light.direction + surface.viewDirection);
 float LoH = dot(light.direction, h);

 if(_DisneyDiffuse == 0)
 return GGX(surface, brdf, light) * FresnelSchlick(surface) * energyCompensation + brdf.diffuse;
 else
 return GGX(surface, brdf, light) * FresnelSchlick(surface) * energyCompensation + (1 / PI * disneyDiffuse(dot(surface.normal, surface.viewDirection), NoL, LoH, brdf.roughness) * brdf.diffuse);

}

Com isso também vamos implementar uma opção para mapas de Roughness em vez de Smoothnes

PBR.shader

Código:
[Enum(Smoothness, 0, Roughness, 1)] _UseRoughness("Smoothness/Roughness", Float) = 0
 [NoScaleOffset] _SmoothnessMap("Smoothness Map(Specular)", 2D) = "white" {} //Mapa de nivel de suavidade

PBRPass.hlsl

Código:
float _UseRoughness;
Código:
 if (_UseRoughness == 0)
 surface.smoothness = smoothness;
 else
 surface.smoothness = PerceptualRoughnessToPerceptualSmoothness(smoothness);

[TUTORIAL] Shader de renderização baseada em física Wiv61ly
Com nivel difuso da Disney


Shader Completo:

Código:
Shader "Magic Byte/Standard PBR" {
 
 Properties {

 _BaseMap("Texture", 2D) = "white" {} //Mapa de textura
 _BaseColor("Color", Color) = (0.5, 0.5, 0.5, 1.0) //Cor de material

 [Enum(Off, 0, On, 1)] _DisneyDiffuse("Disney Diffuse", Float) = 1 //On

 _Metallic("Metallic", Range(0, 1)) = 0 //Nivel metalico (0,1)
 _Smoothness("Smoothness", Range(0, 1)) = 0.5 //Nivel de "superficie aspera" ou nivel de suavidade
 _Occlusion("Occlusion", Range(0, 1)) = 1 //Nivel de microsombras do mapa de oclusao

 [NoScaleOffset] _OcclusionMap("Occlusion Map(AO)", 2D) = "white" {} //Mapa de Oclusao
 [Enum(Smoothness, 0, Roughness, 1)] _UseRoughness("Smoothness/Roughness", Float) = 0
 [NoScaleOffset] _SmoothnessMap("Smoothness Map(Specular)", 2D) = "white" {} //Mapa de nivel de suavidade
 [NoScaleOffset] _MetalMap("Metallic Map", 2D) = "white" {} //Mapa de nivel metalico

 [NoScaleOffset] _EmissionMap("Emission", 2D) = "white" {} //Mapa de emissao
 [HDR] _EmissionColor("Emission", Color) = (0.0, 0.0, 0.0, 0.0) //Cor da emissao

 [NoScaleOffset] _NormalMap("Normals", 2D) = "bump" {} //Mapa normal
 _NormalStrength("Normal Strength", Range(0, 1)) = 1 //Nivel de mapa normal
 
     _Fresnel("Reflectance", Range(0,3)) = 0.0 //Reflectancia do material. (0,3) Para fins artisticos

 /*Blend options*/
 [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend", Float) = 1 //One
 [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend", Float) = 0 //Zero
 [Enum(Off, 0, On, 1)] _ZWrite ("Z Write", Float) = 1 //On
 /*Blend options*/

 [HideInInspector] _MainTex("Lightmap Texture", 2D) = "white" {} // Uso de GI em SRP (Retrire essas propriedades)
 [HideInInspector] _Color("Lightmap Color", Color) = (0.5, 0.5, 0.5, 1.0) // Uso de GI em SRP (Retrire essas propriedades)
 }
 
 SubShader {
 HLSLINCLUDE
 #include "../../ShaderLibrary/Common.hlsl" //API de graficos da MB (Retire esse include)
 ENDHLSL

 Pass {
 Tags {
 "LightMode" = "MBLit"
 }

 /*Blend*/
 Blend [_SrcBlend] [_DstBlend]
 ZWrite [_ZWrite]
 /*Blend*/

 HLSLPROGRAM
 /*Features para SRP*/
 #pragma target 3.5
 #pragma shader_feature _CLIPPING
 #pragma shader_feature _RECEIVE_SHADOWS
 #pragma shader_feature _PREMULTIPLY_ALPHA
 #pragma multi_compile _ LOD_FADE_CROSSFADE
 #pragma multi_compile _ _DIRECTIONAL_PCF3 _DIRECTIONAL_PCF5 _DIRECTIONAL_PCF7
 #pragma multi_compile _ _CASCADE_BLEND_SOFT _CASCADE_BLEND_DITHER
 #pragma multi_compile _ _SHADOW_MASK_ALWAYS _SHADOW_MASK_DISTANCE 
 #pragma multi_compile _ LIGHTMAP_ON
 #pragma multi_compile _ DYNAMICLIGHTMAP_ON
 #pragma multi_compile_instancing
 /*Features para SRP*/

 #pragma vertex PBRPassVertex // <-- VERTEX SHADER
 #pragma fragment PBRPassFragment // <-- PIXEL SHADER
 #include "PBRPass.hlsl" // <-- Incluir Arquivo com os Pass
 ENDHLSL
 }

 }
}


Código:
#ifndef PBR_PASS_INCLUDED
#define PBR_PASS_INCLUDED

/* API GRAFICA MB */
#include "../../ShaderLibrary/Surface.hlsl"
#include "../../ShaderLibrary/Shadows.hlsl"
#include "../../ShaderLibrary/Light.hlsl"
#include "../../ShaderLibrary/BRDF.hlsl"
#include "../../ShaderLibrary/GI.hlsl"
#include "../../ShaderLibrary/Lighting.hlsl"
#include "../../ShaderLibrary/ClearCoat.hlsl"
/* API GRAFICA MB */

TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);

TEXTURE2D(_NormalMap);
SAMPLER(sampler_NormalMap);

TEXTURE2D(_OcclusionMap);
SAMPLER(sampler_OcclusionMap);

TEXTURE2D(_SmoothnessMap);
SAMPLER(sampler_SmoothnessMap);

TEXTURE2D(_MetalMap);
SAMPLER(sampler_MetalMap);

TEXTURE2D(_EmissionMap);
SAMPLER(sampler_EmissionMap);

float4 _BaseColor;
float _NormalStrength;
float _Metallic;
float _Smoothness;
float _Occlusion;
float4 _EmissionColor;
float _Fresnel;
float _DisneyDiffuse;
float _UseRoughness;

struct BRDFstruct {
 float3 diffuse;
 float3 specular;
 float perceptualRoughness;
 float roughness;
};

#define MIN_REFLECTIVITY 0.04

float OneMinReflectivity(float metallic) {
 float size = 1.0 - MIN_REFLECTIVITY;
 return size - metallic * size;
}

BRDFstruct GetBRDFstruct(Surface surface) {
 BRDFstruct brdf;

 brdf.diffuse = surface.color * OneMinReflectivity(surface.metallic);
 brdf.specular = lerp(MIN_REFLECTIVITY, surface.color, surface.metallic);

 brdf.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surface.smoothness);
 brdf.roughness = PerceptualRoughnessToRoughness(brdf.perceptualRoughness);

 return brdf;
}

//GGX
float GGX(Surface surface, BRDFstruct brdf, Light light) {
 float3 h = SafeNormalize(light.direction + surface.viewDirection); //Half Vector (Vetor Mediano)
 float NoH = dot(surface.normal, h); //Produto escalar entre vetor normal e vetor mediano
 float3 NxH = cross(surface.normal, h);//Produto cruzado entre vetor normal e vetor mediano
 float a = NoH * brdf.roughness;
 float k = brdf.roughness / (dot(NxH, NxH) + a * a);
 float d = k * k * (1.0 / PI);//  1/PI <-- Essa e a funcao lambertiana | A divisão por pi existe para normalizar a luz
 return d;
}

float FresnelSchlick(Surface surface) {
 float NoV = dot(surface.normal, surface.viewDirection);
 float f0 = pow(1.0 - NoV, 4.0);//Potencia da 4 grau no inverso (OneMinus) do produto escalar
 return f0 + NoV * (1.0 - f0) * surface.metallic;
}

float FresnelTransmission(float f0, float f90, float u)
{
 real x = 1.0 - u;
 real x2 = x * x;
 real x5 = x * x2 * x2;
 return (1.0 - f90 * x5) - f0 * (1.0 - x5);
}

float Diffuse(float NoV, float NoL, float LoH, float roughness)
{
 float  energyBias = lerp(0, 0.7, roughness);
 float  energyFactor = lerp(1.0, 1.0 / 1.51, roughness);
 float  fd90 = energyBias + 1.0 * LoH * LoH * roughness;
 float f0 = 1.0f;
 float lightScatter = FresnelTransmission(f0, fd90, NoL);//Controle de transmissao de energia
 float viewScatter = FresnelTransmission(f0, fd90, NoV);
 return  lightScatter * viewScatter * energyFactor;
}

float3 DirectIllumination(Surface surface, BRDFstruct brdf, Light light) {

 float NoL = dot(surface.normal, light.direction);//Produto escalar entre o vetor Normal e o vetor de direcao da luz
 float3 energyCompensation = 1.0 + NoL * (1.0 / (1.1 - brdf.roughness) - 1.0);

 float3 h = SafeNormalize(light.direction + surface.viewDirection);
 float LoH = dot(light.direction, h);

 if(_DisneyDiffuse == 0)
 return GGX(surface, brdf, light) * FresnelSchlick(surface) * energyCompensation + brdf.diffuse;
 else
 return GGX(surface, brdf, light) * FresnelSchlick(surface) * energyCompensation + (1 / PI * Diffuse(dot(surface.normal, surface.viewDirection), NoL, LoH, brdf.roughness) * brdf.diffuse);

}

float3 IndirectIllumination(Surface surface, BRDFstruct brdf, float3 diffuse, float3 specular) {

 float3 reflection = specular * lerp(brdf.specular, saturate(surface.smoothness + 1.0 - OneMinReflectivity(surface.metallic)), FresnelSchlick(surface));
 reflection /= brdf.roughness * brdf.roughness + 1.0;

 return (diffuse * (brdf.diffuse / PI) + reflection) * surface.occlusion;
}

struct Attributes {
 float3 positionOS : POSITION;
 float3 normalOS : NORMAL;
 float4 tangentOS : TANGENT;
 float2 baseUV : TEXCOORD0;
 float2 lightmapUV: TEXCOORD1;
 float2 dynamicLightmapUV : TEXCOORD2;
 UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct Varyings {
 float4 positionCS : SV_POSITION;
 float3 positionWS : VAR_POSITION;
 float3 normalWS : VAR_NORMAL;
 float4 tangentWS : VAR_TANGENT;
 float2 baseUV : VAR_BASE_UV;
 float2 lightmapUV : TEXCOORD4;
 float2 dynamicLightmapUV : TEXCOORD5;
 UNITY_VERTEX_INPUT_INSTANCE_ID
};

Varyings PBRPassVertex (Attributes input) {
 Varyings output;

 /* API GRAFICA MB */
 output.lightmapUV = input.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;
 output.dynamicLightmapUV = input.dynamicLightmapUV * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
 /* API GRAFICA MB */

 /* Render Pipelines Core */
 output.positionWS = TransformObjectToWorld(input.positionOS);
 output.positionCS = TransformWorldToHClip(output.positionWS);
 output.normalWS = TransformObjectToWorldNormal(input.normalOS);
 output.tangentWS = float4(TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w);
 output.baseUV = input.baseUV;
 /* Render Pipelines Core */

 return output;
}

float4 _Time; //Funcao tempo importada da unity por buffer

float3 Lighting(Surface surface, GI gi) {
 ShadowData shadowData = GetShadowData(surface);
 shadowData.shadowMask = gi.shadowMask;

 BRDFstruct brdf = GetBRDFstruct(surface);

 float3 color = IndirectIllumination(surface, brdf, gi.diffuse, gi.specular);
 for (int i = 0; i < GetDirectionalLightCount(); i++) {
 Light light = GetDirectionalLight(i, surface, shadowData);//Compilar Luz
 color += dot(surface.normal, light.direction) * light.attenuation * light.color;
 color *= DirectIllumination(surface, brdf, light);//Adicionar sombra propria
 }
 return color;
}

float4 PBRPassFragment(Varyings input) : SV_TARGET{
 float3 color = (0,0,0);

 Surface surface;
 surface.position = input.positionWS;

 float4 Nmap = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.baseUV);
 float3 normal = DecodeNormal(Nmap, _NormalStrength);

 surface.normal = NormalTangentToWorld(normal, input.normalWS, input.tangentWS); // <---- Transformacao de espaco do Render Pipelines Core
 surface.interpolatedNormal = input.normalWS;
 surface.viewDirection = normalize(_WorldSpaceCameraPos - input.positionWS); //Normalizar posicao da camera - posicao de objeto
 surface.tangent = input.tangentWS;
 surface.binormal = cross(NormalTangentToWorld(normal, input.normalWS, input.tangentWS), input.tangentWS.xyz) * input.tangentWS.w;
 surface.color = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.baseUV) * _BaseColor.rgb;
 surface.alpha = _BaseColor.a;

 float metallic = _Metallic;
 metallic *= pow(abs(SAMPLE_TEXTURE2D(_MetalMap, sampler_MetalMap, input.baseUV).r), 2.2); //Correcao de Gamma do mapa (Fins artisticos)

 float smoothness = _Smoothness;
 smoothness *= pow(abs(SAMPLE_TEXTURE2D(_SmoothnessMap, sampler_SmoothnessMap, input.baseUV).r), 2.2); //Correcao de Gamma do mapa (Fins artisticos)
 
 float occlusion = _Occlusion;
 occlusion *= pow(abs(SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, input.baseUV).r), 2.2); //Correcao de Gamma do mapa (Fins artisticos)

 surface.metallic = metallic;
 if (_UseRoughness == 0)
 surface.smoothness = smoothness;
 else
 surface.smoothness = PerceptualRoughnessToPerceptualSmoothness(smoothness);
 surface.occlusion = occlusion;

 surface.fresnelStrength = _Fresnel;

 GI gi = GetGI(input.lightmapUV, input.dynamicLightmapUV, surface, (1 - surface.smoothness), 1);
 color = Lighting(surface, gi);

 color += SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, input.baseUV) * _EmissionColor;

 return float4(color, surface.alpha);
}

#endif

Na Magic Byte, os shader PBR recebem ainda o Clear Coat e o especular anisotrópico, que não serão abordados nesse tutorial por fugirem um pouco da parte que eu queria mostrar.



Esse foi a tutorial sobre teoria de PBR! Espero que seja útil para alguém. Vergonhoso
Matrirxp
Matrirxp
ProgramadorMaster

Masculino PONTOS : 1865
REPUTAÇÃO : 78
Idade : 18
Áreas de atuação : Programação: C#, Java,C++,JavaScript.
Modelagem 3D.
Respeito as regras : [TUTORIAL] Shader de renderização baseada em física Aad8pUi

https://www.youtube.com/channel/UCkngjEDMx9y_vW0t7Io05gg

Voltar ao Topo Ir em baixo

TUTORIAL Re: [TUTORIAL] Shader de renderização baseada em física

Mensagem por NKKF em Dom Out 18, 2020 1:17 am

Código:

//
/*    */


Sem comentários 

[TUTORIAL] Shader de renderização baseada em física E795d3bfaa35b8843bf27b83e65a111d
NKKF
NKKF
ProgramadorMaster

Masculino PONTOS : 3168
REPUTAÇÃO : 520
Idade : 16
Áreas de atuação : Desenvolvedor na Unity, NodeJS, React, ReactJS, React Native, MongoDB e Firebase.
Respeito as regras : [TUTORIAL] Shader de renderização baseada em física Aad8pUi

Voltar ao Topo Ir em baixo

Voltar ao Topo


 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum