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:
Como definir um limite de itens guardados num inventário
Loja no game, duvidas sobre voltar para a cena após usar a loja.
O Collider não funciona
Dúvida em relação a Unity + MySql + PHP
Como fazer com que objetos spawnem por vez em uma array
Unity - Scriptable Objects [PT-BR]
Como faço pro personagem correr na direção da câmera para Android
Nao estou a conseguir mudar o transform.position do meu fps
Como aceder a pontuação correta no outro script
2 objetos utilizando mesmo script na hora de instanciar
[TUTORIAL] Identificar qual a melhor qualidade gráfica baseada no Hardware
[DUVIDA]confirar automaticamente para cada hardware
Qual é a lógica do terreno do Minecraft?
IA inimigo!
a rotacao do player esta errada!
Não consigo mais abrir projeto nenhum na Unity!
como configurar um layer para que ele ignore o Raycast
Alguém sabe como corrigir esse bug visual na interface do editor da unity?
[TUTORIAL] Sistema de DIA E NOITE completo, com luzes noturnas e SISTEMA DE NUVENS
sistema de matar o inimigo estilo among us
Random Terrain Generation
Rotacionar objeto e mover para a direita e para a esquerda
como fazer o player sair do carro?
[____TÓPICO LIVRE____] FALE O QUE QUISER (Parte 2)
[TUTORIAL] Unity 3D - Fazer algo ao clicar em um objeto
[RESOLVIDO] Como fazer uma parede que se move sozinha empurrar o Player?
Implementar geração de terrenos com interpolação bicúbica
Posso fazer jogos com gráficos e áudio dos consoles da terceira geração?
Como ativa ou desativar o botão usando outro botão
Dúvida sobre Instanciate
posso divulgar o fórum em meu site?
build settings parou de funcionar!!!
como desativar um script usando botão na unity
como fazer botão simular uma tecla do teclado para jogos android unity
Clonar partícula na cena.
Preciso de ajuda com GetMouseButton para dar play em audio
TRIGGER DE ANIMAÇÃO
Otimização
[RESOLVIDO] Rotação de um gameobject sem que os filhos se alterem?
Trigger Raio e Trovão
Não consigo desativar script de gameObject (C#)
Alguém poderia mudar esse script pra botão
Como desativar e habilitar o Skinned MeshRenderer?
Como transformar um vídeo em espaço editável na Unity?
[TUTORIAL] Inimigo seguir e atacar Player ao encostar
Trocar Personagem/Skin
Como faz para o jogo rodar mesmo quando minimizado?
Alguem poderia me ajudar com combo 2d?
Jogador pode escolher que tipo de pos processamento usar nas configurações?
Como se faz um sistema de combo pra mobile
Como fazer com que collider detecte colisao de objeto especifico?
Problema mudar de sprite sempre que seja adicionado um novo sprite a lista
Colocar video no unity
Imagem excedendo o limite da tela. Como resolver?
Erro no Android
Como abrir uma empresa de games?
Informação Importante sobre o Edge Collider 2D
Como consigo aquele efeito de lanterna imagem abaixo
Como posso usar a função OnClick nesse script
[TUTORIAL] Como carregar uma cena em segundo plano?
[Tutorial] Sistema de Combos (Mobile e PC)
Personagem sofre dando e continua de onde parou com condição.
Como Abrir Porta do Carro (Capo,PortaMalas, Portas) Mirando Nelas
[RESOLVIDO] Várias faixas de música
[RESOLVIDO] int Random.Range(int min, int max) para geração procedural ?
Como fazer o som funcionar de acordo com a velocidade do objeto
Alto falante Vibrar
[RESOLVIDO] Luz no interior
[TUTORIAL] Como Fazer com que as Luzes Iluminem apenas o que você deseja
Traduções e Dublagens de games
[RESOLVIDO] Cono mudar a Tag por script?
[RESOLVIDO] Qualidade do sprite - Compression
[TUTORIAL] Unity 3D - AnimationCurve
[RESOLVIDO] Partículas com imagem
[RESOLVIDO] DUVIDA SOBRE ATIVAR UM GAMEOBJECT ATRAVÉS DE UMA CONDIÇÃO
NavMesh não consegue reproduzir sprits de um jogador
NavMesh não faz animação do jogador
Bom dia amigos compro assets do meu interesse!
Criar Ranking Online
[TUTORIAL] ScrollView rapida e facil de fazer
colocar imagem no fórum
Unity ou Game Maker Studio
[TUTORIAL] Tocar audios de uma lista em uma sequência que se repete
Error CS0246, não sei o que fazer
Como faço pra um colisor não reconhecer outro colisor sem usar IsTrigger
[RESOLVIDO] Alteração de nomes e rastreamento das mudanças
Som unity
CHAVE DE ASSINATURA
[TUTORIAL]identificar se está no controle ou teclado
[TUTORIAL] Sistema de fome, sede, barra de vida, barra de estamina, itens e dano por queda
Não estou conseguindo ativar o evento do onClick após instanciar o botão
Exportar Modelo 3D da Unity
Duvida sobre Spawn
Dúvida sobre volatile
[UE4] Por favor me digam como me livrar do motion blur!
[RESOLVIDO] Float to transform
[RESOLVIDO] mudar a cor quando a personagem passa
Como ativar um 'Panel'
Como faço pra desligar e ligar outro text?
Hoje à(s) 4:23 am
Ontem à(s) 11:39 pm
Ontem à(s) 11:11 am
Ontem à(s) 11:01 am
Ontem à(s) 1:46 am
Ter Jan 26, 2021 11:36 pm
Ter Jan 26, 2021 7:35 pm
Ter Jan 26, 2021 5:53 pm
Ter Jan 26, 2021 5:31 pm
Ter Jan 26, 2021 3:21 pm
Seg Jan 25, 2021 5:39 pm
Seg Jan 25, 2021 4:58 pm
Seg Jan 25, 2021 2:51 pm
Seg Jan 25, 2021 10:21 am
Seg Jan 25, 2021 9:56 am
Seg Jan 25, 2021 9:24 am
Seg Jan 25, 2021 5:15 am
Seg Jan 25, 2021 2:05 am
Seg Jan 25, 2021 2:00 am
Seg Jan 25, 2021 1:40 am
Seg Jan 25, 2021 12:36 am
Dom Jan 24, 2021 10:31 pm
Dom Jan 24, 2021 4:48 pm
Dom Jan 24, 2021 4:40 pm
Dom Jan 24, 2021 3:41 pm
Dom Jan 24, 2021 3:14 pm
Dom Jan 24, 2021 10:24 am
Sab Jan 23, 2021 3:15 pm
Sab Jan 23, 2021 1:19 pm
Sab Jan 23, 2021 12:24 pm
Sab Jan 23, 2021 11:57 am
Sab Jan 23, 2021 11:49 am
Sex Jan 22, 2021 4:27 pm
Sex Jan 22, 2021 2:32 pm
Sex Jan 22, 2021 2:25 pm
Sex Jan 22, 2021 12:41 pm
Sex Jan 22, 2021 10:12 am
Sex Jan 22, 2021 9:47 am
Sex Jan 22, 2021 3:34 am
Sex Jan 22, 2021 1:06 am
Qui Jan 21, 2021 10:59 pm
Qui Jan 21, 2021 7:56 pm
Qui Jan 21, 2021 5:11 pm
Qui Jan 21, 2021 3:47 pm
Qui Jan 21, 2021 11:17 am
Qui Jan 21, 2021 10:45 am
Qui Jan 21, 2021 9:54 am
Qua Jan 20, 2021 11:55 pm
Qua Jan 20, 2021 11:53 pm
Qua Jan 20, 2021 11:07 pm
Qua Jan 20, 2021 9:52 pm
Qua Jan 20, 2021 5:29 pm
Qua Jan 20, 2021 4:58 pm
Qua Jan 20, 2021 3:56 pm
Qua Jan 20, 2021 3:53 pm
Qua Jan 20, 2021 9:26 am
Ter Jan 19, 2021 10:30 pm
Ter Jan 19, 2021 8:28 pm
Ter Jan 19, 2021 4:48 pm
Ter Jan 19, 2021 6:49 am
Seg Jan 18, 2021 11:39 pm
Seg Jan 18, 2021 9:31 pm
Seg Jan 18, 2021 10:47 am
Seg Jan 18, 2021 10:34 am
Dom Jan 17, 2021 10:54 pm
Dom Jan 17, 2021 6:28 pm
Dom Jan 17, 2021 2:07 pm
Dom Jan 17, 2021 12:21 pm
Dom Jan 17, 2021 11:19 am
Dom Jan 17, 2021 11:17 am
Dom Jan 17, 2021 11:15 am
Dom Jan 17, 2021 1:44 am
Sab Jan 16, 2021 6:40 pm
Sab Jan 16, 2021 11:43 am
Sab Jan 16, 2021 11:12 am
Sex Jan 15, 2021 8:20 pm
Sex Jan 15, 2021 1:39 am
Qui Jan 14, 2021 9:53 pm
Qui Jan 14, 2021 7:44 pm
Qui Jan 14, 2021 5:35 pm
Qui Jan 14, 2021 3:55 pm
Qui Jan 14, 2021 2:07 pm
Qui Jan 14, 2021 1:51 pm
Qui Jan 14, 2021 12:56 pm
Qua Jan 13, 2021 6:57 pm
Qua Jan 13, 2021 2:45 pm
Ter Jan 12, 2021 11:14 pm
Ter Jan 12, 2021 8:14 pm
Ter Jan 12, 2021 3:16 pm
Seg Jan 11, 2021 6:26 pm
Seg Jan 11, 2021 5:55 pm
Seg Jan 11, 2021 10:51 am
Dom Jan 10, 2021 7:18 pm
Dom Jan 10, 2021 6:21 pm
Dom Jan 10, 2021 3:24 pm
Dom Jan 10, 2021 2:31 pm
Dom Jan 10, 2021 2:29 pm
Dom Jan 10, 2021 10:44 am
Sab Jan 09, 2021 9:30 pm
sticktotss
Fagner
SauloeArthur
mateus.ribas
speedluk
NKKF
Vans 123
Pokedlg
Pokedlg
darkrj
Pokedlg
Pokedlg
Sasuke rei
pinguso51
Pokedlg
sopturn
Maleos
JulioWinchester
gael
gui78h3
JulioWinchester
Pokedlg
Pokedlg
MarcosSchultz
gui78h3
Pokedlg
Harcher
dutrabr100
Pokedlg
Pokedlg
dutrabr100
SauloeArthur
Vans 123
SauloeArthur
Pokedlg
Charlesoff
Pokedlg
Fagner
ADSK
Pokedlg
wooZbr
Pokedlg
Pokedlg
dutrabr100
SauloeArthur
dutrabr100
NKKF
dutrabr100
dutrabr100
Pokedlg
SamoelBanner
Pokedlg
SauloeArthur
NKKF
orph
dutrabr100
acefogo
Fagner
Vans 123
amoraleite
Pokedlg
acefogo
dutrabr100
Pokedlg
dutrabr100
Pokedlg
savtoi
dragongirl
dutrabr100
Rangel Oblivion
dutrabr100
JoelMJunior
MarcosSchultz
dragongirl
dutrabr100
Ren Allen
Ren Allen
LucasGamerFx
SauloeArthur
NKKF
dutrabr100
SauloeArthur
Pokedlg
SauloeArthur
dutrabr100
Alexandre Santos
Pokedlg
starfreddybou69
diegopds
Super
dutrabr100
TIKO
dutrabr100
SauloeArthur
lesgoy
Fagner
Pokedlg
dutrabr100
Pokedlg

[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
Buffer _Time

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:
Arquivo de GI utilizado: GI.hlsl
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
D(h): Função de distribuição (Modelo usado GGX)
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!


Última edição por Matrirxp em Qui Jan 07, 2021 11:20 am, editado 1 vez(es)
Matrirxp
Matrirxp
ProgramadorMaster

Masculino PONTOS : 1965
REPUTAÇÃO : 78
Idade : 18
Áreas de atuação : Programação: C#, Java, HLSL, CG, GLSL.
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 : 3300
REPUTAÇÃO : 528
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

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

Mensagem por glauco em Qui Out 22, 2020 11:50 am

Parabéns!!!!!!!!!!!!!!

Caralho eu como uma pesosa "leiga" não consigo entender direito kk

Eu lí o seu tópico e percebi que está bem detalhado e explicado, ficou muito bom mesmo kkk

Fico até triste por não conseguir encontrar um amigo do seu nivel kk
glauco
glauco
MembroAvançado

Masculino PONTOS : 2168
REPUTAÇÃO : 118
Idade : 21
Áreas de atuação : unity 3D...
Level Design
aprendendo modelagem
se aperfeiçoando na unity 3D

Respeito as regras : [TUTORIAL] Shader de renderização baseada em física WvDYdlf

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