parent
4c56060260
commit
b4e564f8b6
|
|
@ -1,21 +1,21 @@
|
|||
[vk::binding(0, 0)] uniform __DynamicResource<__DynamicResourceKind.Sampler> gTextures[];
|
||||
[vk::binding(0, 0)] uniform __DynamicResource<__DynamicResourceKind.Sampler> g_Textures[];
|
||||
|
||||
public struct RID<T> where T : IOpaqueDescriptor {
|
||||
private uint internal;
|
||||
private uint m_internal;
|
||||
|
||||
private const static uint INDEX_MASK = 0x0007FFFF;
|
||||
private const static uint GENERATION_MASK = ~INDEX_MASK;
|
||||
|
||||
public property bool hasValue {
|
||||
get {
|
||||
return (internal & GENERATION_MASK) > 0;
|
||||
return (m_internal & GENERATION_MASK) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public property T value {
|
||||
get {
|
||||
// TODO: Check if has value else placeholder.
|
||||
return gTextures[internal & INDEX_MASK].asOpaqueDescriptor<T>();
|
||||
return g_Textures[m_internal & INDEX_MASK].asOpaqueDescriptor<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import Bindless;
|
||||
import PBR;
|
||||
|
||||
public struct Material {
|
||||
float4 baseColor;
|
||||
|
|
@ -10,54 +11,70 @@ public struct Material {
|
|||
float metallic;
|
||||
float roughness;
|
||||
|
||||
public float4 getAlbedo(float2 uv, float4 inColor) {
|
||||
if (let albedoTex = albedoTextureID) {
|
||||
return baseColor * albedoTex.Sample(uv).rgba;
|
||||
float4 GetAlbedo(float2 uv, float4 in_color) {
|
||||
if (let albedo_tex = albedoTextureID) {
|
||||
return in_color * baseColor * albedo_tex.Sample(uv).rgba;
|
||||
}
|
||||
return baseColor;
|
||||
return baseColor * in_color;
|
||||
}
|
||||
|
||||
public float3 getEmissive(float2 uv) {
|
||||
if (let emissionTex = emissiveTextureID) {
|
||||
return emissionTex.Sample(uv).rgb * emissiveColor.rgb * emissiveColor.a;
|
||||
public float3 GetEmissive(float2 uv) {
|
||||
if (let emission_tex = emissiveTextureID) {
|
||||
return emission_tex.Sample(uv).rgb * emissiveColor.rgb * emissiveColor.a;
|
||||
}
|
||||
return emissiveColor.rgb * emissiveColor.a;
|
||||
}
|
||||
|
||||
public float3 getNormal(float3 position, float3 normal, float4 tangent, float2 uv) {
|
||||
float3 N = normalize(normal.xyz);
|
||||
float3 GetNormal(float3 position, float3 vert_normal, float4 vert_tangent, float2 uv) {
|
||||
float3 normal = normalize(vert_normal.xyz);
|
||||
|
||||
if (let normalTex = normalTextureID) {
|
||||
let vNt = normalize(2.0f * normalTex.Sample(uv).rgb - 1.0f);
|
||||
if (let normal_tex = normalTextureID) {
|
||||
let normal_tanspace = normalize(2.0f * normal_tex.Sample(uv).rgb - 1.0f);
|
||||
|
||||
float3 T;
|
||||
float3 B;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
|
||||
if (tangent.w == 0.0f) {
|
||||
float3 q1 = ddx(position);
|
||||
float3 q2 = ddy(position);
|
||||
if (vert_tangent.w == 0.0f) {
|
||||
float3 q1 = ddx(position);
|
||||
float3 q2 = ddy(position);
|
||||
float2 st1 = ddx(uv);
|
||||
float2 st2 = ddy(uv);
|
||||
|
||||
float det = (st1.x * st2.y - st2.x * st1.y);
|
||||
float det = (st1.x * st2.y - st2.x * st1.y);
|
||||
|
||||
T = -(q1 * st2.y - q2 * st1.y) / det;
|
||||
T = T - N * dot(N, T);
|
||||
B = normalize(cross(N, T));
|
||||
tangent = -(q1 * st2.y - q2 * st1.y) / det;
|
||||
tangent = tangent - normal * dot(normal, tangent);
|
||||
bitangent = normalize(cross(normal, tangent));
|
||||
} else {
|
||||
T = normalize(tangent.xyz);
|
||||
B = tangent.w * cross(N, T);
|
||||
tangent = normalize(vert_tangent.xyz);
|
||||
bitangent = vert_tangent.w * cross(normal, tangent);
|
||||
}
|
||||
N = normalize(T * vNt.x + B * vNt.y + N * vNt.z);
|
||||
normal = normalize(tangent * normal_tanspace.x + bitangent * normal_tanspace.y + normal * normal_tanspace.z);
|
||||
}
|
||||
|
||||
return N;
|
||||
return normal;
|
||||
}
|
||||
|
||||
public float2 getMetalRough(float2 uv) {
|
||||
if (let metalRoughTex = metalRoughTextureID) {
|
||||
return metalRoughTex.Sample(uv).bg * float2(metallic, roughness);
|
||||
float2 GetMetalRough(float2 uv) {
|
||||
if (let metal_rough_tex = metalRoughTextureID) {
|
||||
return metal_rough_tex.Sample(uv).bg * float2(metallic, roughness);
|
||||
}
|
||||
return float2(metallic, roughness);
|
||||
}
|
||||
|
||||
public IBRDF GetBRDF(
|
||||
float2 uv,
|
||||
float3 position,
|
||||
float3 vertex_normal,
|
||||
float4 vertex_tangent,
|
||||
float4 vertex_color)
|
||||
{
|
||||
float3 normal = GetNormal(position, vertex_normal, vertex_tangent, uv);
|
||||
float2 metal_rough = GetMetalRough(uv);
|
||||
float3 albedo = GetAlbedo(uv, vertex_color).xyz;
|
||||
float3 f0 = 0.04f.xxx;
|
||||
f0 = lerp(f0, albedo, metal_rough.x);
|
||||
|
||||
return BRDFCookTorranceGGX(albedo, metal_rough.x, normal, metal_rough.y, f0);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,14 @@ struct VertexOut {
|
|||
struct CameraData {
|
||||
float4x4 view;
|
||||
float4x4 proj;
|
||||
float4 position;
|
||||
float4 position;
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
float3 position;
|
||||
float range;
|
||||
float3 color;
|
||||
float attenuation;
|
||||
};
|
||||
|
||||
struct DirectionalLight {
|
||||
|
|
@ -26,25 +33,15 @@ struct DirectionalLight {
|
|||
};
|
||||
|
||||
struct LightData {
|
||||
PointLight* pointLights;
|
||||
PointLight* pointLights;
|
||||
DirectionalLight* dirLights;
|
||||
uint pointLightCount;
|
||||
uint dirLightCount;
|
||||
|
||||
PointLight getPointLight(uint idx) {
|
||||
if (idx >= pointLightCount) return pointLights[0];
|
||||
return pointLights[idx];
|
||||
}
|
||||
|
||||
DirectionalLight getDirectionalLight(uint idx) {
|
||||
if (idx >= dirLightCount) return dirLights[0];
|
||||
return dirLights[idx];
|
||||
}
|
||||
uint pointLightCount;
|
||||
uint dirLightCount;
|
||||
};
|
||||
|
||||
struct PerFrameData {
|
||||
CameraData camera;
|
||||
LightData lightData;
|
||||
CameraData camera;
|
||||
LightData lightData;
|
||||
};
|
||||
|
||||
uniform ParameterBlock<PerFrameData> pfd;
|
||||
|
|
@ -64,203 +61,64 @@ VertexOut VertexMain(
|
|||
float3 position,
|
||||
float3 normal,
|
||||
float4 tangent,
|
||||
float2 texCoord0,
|
||||
float2 texCoord1,
|
||||
float4 vertexColor0,
|
||||
float2 uv0,
|
||||
float2 uv1,
|
||||
float4 vertex_color0,
|
||||
) {
|
||||
float4 worldPosition = mul(pcb.transform, float4(position, 1.0f));
|
||||
|
||||
VertexOut output;
|
||||
output.outPosition = mul(pfd.camera.proj, mul(pfd.camera.view, worldPosition));
|
||||
output.worldPosition = worldPosition;
|
||||
output.normal = normalize(mul(float4(normal.xyz, 0.0f), pcb.invTransform).xyz);
|
||||
float4 worldPosition = mul(pcb.transform, float4(position, 1.0f));
|
||||
|
||||
output.outPosition = mul(pfd.camera.proj, mul(pfd.camera.view, worldPosition));
|
||||
output.worldPosition = worldPosition;
|
||||
output.normal = normalize(mul(float4(normal.xyz, 0.0f), pcb.invTransform).xyz);
|
||||
if (tangent.w == 0.0f) {
|
||||
output.tangent = 0.0f.xxxx;
|
||||
} else {
|
||||
output.tangent = float4(normalize(mul(float4(tangent.xyz, 0.0f), pcb.invTransform).xyz), tangent.w);
|
||||
}
|
||||
output.texCoord0 = texCoord0;
|
||||
output.texCoord1 = texCoord1;
|
||||
output.vertexColor0 = vertexColor0;
|
||||
output.texCoord0 = uv0;
|
||||
output.texCoord1 = uv1;
|
||||
output.vertexColor0 = vertex_color0;
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
float TrowbridgeReitzGGX(float3 Normal, float3 Halfway, float Roughness)
|
||||
{
|
||||
float Coeff = Roughness * Roughness;
|
||||
float Alpha2 = Coeff * Coeff;
|
||||
float NdotH = max(dot(Normal, Halfway), 0.0f);
|
||||
float NdotH2 = NdotH * NdotH;
|
||||
|
||||
float Numerator = Alpha2;
|
||||
float Denominator = NdotH2 * (Alpha2 - 1.0f) + 1.0f;
|
||||
Denominator = PI * Denominator * Denominator;
|
||||
|
||||
return Numerator / Denominator;
|
||||
}
|
||||
|
||||
float GeometrySchlickGGX(float NdotV, float Roughness)
|
||||
{
|
||||
float R = Roughness + 1.0f;
|
||||
float K = (R * R) / 8.0f;
|
||||
|
||||
float Numerator = NdotV;
|
||||
float Denominator = NdotV * (1.0f - K) + K;
|
||||
|
||||
return Numerator / Denominator;
|
||||
}
|
||||
|
||||
float GeometrySmith(float NdotV, float NdotL, float Roughness)
|
||||
{
|
||||
float GGX1 = GeometrySchlickGGX(NdotV, Roughness);
|
||||
float GGX2 = GeometrySchlickGGX(NdotL, Roughness);
|
||||
|
||||
return GGX1 * GGX2;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Schlick%27s_approximation
|
||||
float3 FresnelSchlick(float cosine, float3 F_0)
|
||||
{
|
||||
return F_0 + (1.0f - F_0) * pow(clamp(1.0f - cosine, 0.0f, 1.0f), 5.0f); // Clamp to avoid artifacts.
|
||||
}
|
||||
|
||||
// Sebastian Lagarde
|
||||
float3 FresnelSchlickRoughness(float cosine, float3 F_0, float Roughness)
|
||||
{
|
||||
return F_0 + (max((1.0f - Roughness).xxx, F_0) - F_0) * pow(clamp(1.0f - cosine, 0.0f, 1.0f), 5.0f); // Clamp to avoid artifacts.
|
||||
}
|
||||
|
||||
float3 GetPBRContrib(float3 Albedo, float3 LightColor, float3 ViewDir, float3 Normal, float Metallic, float Roughness, float3 F_0, float3 LightDir, float LightDistance)
|
||||
{
|
||||
float Attenuation = 1.0f / (LightDistance * LightDistance); // TODO: Controlled Attenuation
|
||||
float3 Halfway = normalize(ViewDir + LightDir);
|
||||
|
||||
float CosineFactor = max(dot(Halfway, ViewDir), 0.0f);
|
||||
float NdotV = max(dot(Normal, ViewDir), 0.0f);
|
||||
float NdotL = max(dot(Normal, LightDir), 0.0f);
|
||||
|
||||
float3 Radiance = LightColor * Attenuation;
|
||||
|
||||
float NormalDistribution = TrowbridgeReitzGGX(Normal, Halfway, Roughness);
|
||||
float Geometry = GeometrySmith(NdotV, NdotL, Roughness);
|
||||
float3 Fresnel = FresnelSchlickRoughness(CosineFactor, F_0, Roughness);
|
||||
|
||||
float3 Numerator = (NormalDistribution * Geometry) * Fresnel;
|
||||
float Denominator = 4.0f * NdotV * NdotL;
|
||||
float3 Specular = Numerator / (Denominator + 0.00001f);
|
||||
|
||||
float3 K_Specular = Fresnel;
|
||||
float3 K_Diffuse = 1.0f.xxx - K_Specular;
|
||||
|
||||
K_Diffuse *= 1.0f - Metallic;
|
||||
|
||||
return NdotL * Radiance * (K_Diffuse * Albedo / PI + Specular);
|
||||
}
|
||||
|
||||
float3 GetPointLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal)
|
||||
{
|
||||
if (pfd.lightData.pointLightCount == 0)
|
||||
return 0.0f.xxx;
|
||||
|
||||
float3 ViewDir = normalize(pfd.camera.position.xyz - Position);
|
||||
|
||||
float Metallic = MetalRough.r;
|
||||
float Roughness = MetalRough.g;
|
||||
|
||||
// Dielectric F_0 based on LearnOpenGL.
|
||||
// TODO: Cite
|
||||
float3 F_0 = 0.04f.xxx;
|
||||
F_0 = lerp(F_0, Albedo, Metallic);
|
||||
|
||||
float3 Contrib = 0.0f;
|
||||
for (uint i = 0; i < pfd.lightData.pointLightCount; ++i)
|
||||
{
|
||||
PointLight Light = pfd.lightData.pointLights[i];
|
||||
|
||||
if (Light.range < 0.0f)
|
||||
continue;
|
||||
|
||||
float3 LightDir = float3(Light.position) - Position;
|
||||
float LightDistance = length(LightDir);
|
||||
|
||||
if (LightDistance > Light.range)
|
||||
continue;
|
||||
|
||||
LightDir /= LightDistance; // Normalization
|
||||
|
||||
// Color Unpack
|
||||
//float R = (Light.Color & 0xFF000000) >> 24;
|
||||
//float G = (Light.Color & 0x00FF0000) >> 16;
|
||||
//float B = (Light.Color & 0x0000FF00) >> 8;
|
||||
|
||||
//float3 LightColor = Light.Intensity * float3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255
|
||||
|
||||
Contrib += GetPBRContrib(Albedo, Light.color, ViewDir, Normal, Metallic, Roughness, F_0, LightDir, LightDistance);
|
||||
}
|
||||
|
||||
return Contrib;
|
||||
}
|
||||
|
||||
float3 GetDirectionalLightInfluence(float3 Albedo, float2 MetalRough, float3 Position, float3 Normal)
|
||||
{
|
||||
if (pfd.lightData.dirLightCount == 0)
|
||||
return 0.0f.xxx;
|
||||
|
||||
float3 ViewDir = normalize(pfd.camera.position.xyz - Position);
|
||||
|
||||
float Metallic = MetalRough.r;
|
||||
float Roughness = MetalRough.g;
|
||||
|
||||
// Dielectric F_0 based on LearnOpenGL.
|
||||
// TODO: Cite
|
||||
float3 F_0 = 0.04f.xxx;
|
||||
F_0 = lerp(F_0, Albedo, Metallic);
|
||||
|
||||
float3 Contrib = 0.0f;
|
||||
for (uint i = 0; i < pfd.lightData.dirLightCount; ++i)
|
||||
{
|
||||
DirectionalLight Light = pfd.lightData.dirLights[i];
|
||||
|
||||
if (Light._padding0 < 0.0f)
|
||||
continue;
|
||||
|
||||
float3 LightDir = -normalize(Light.direction);
|
||||
|
||||
// Color Unpack
|
||||
//float R = (Light.Color & 0xFF000000) >> 24;
|
||||
//float G = (Light.Color & 0x00FF0000) >> 16;
|
||||
//float B = (Light.Color & 0x0000FF00) >> 8;
|
||||
|
||||
//float3 LightColor = Light.Intensity * float3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255
|
||||
|
||||
float3 LightColor = Light.color;
|
||||
|
||||
Contrib += GetPBRContrib(Albedo, LightColor, ViewDir, Normal, Metallic, Roughness, F_0, LightDir, 1.0f);
|
||||
}
|
||||
|
||||
return Contrib;
|
||||
}
|
||||
|
||||
[shader("fragment")]
|
||||
float4 FragmentMain(
|
||||
float4 position : POSITION,
|
||||
float3 normal : NORMAL,
|
||||
float4 tangent : TANGENT,
|
||||
float2 texCoord0 : TEXCOORD0,
|
||||
float2 texCoord1 : TEXCOORD1,
|
||||
float4 vertexColor0 : COLOR0,
|
||||
float4 position : POSITION,
|
||||
float3 normal : NORMAL,
|
||||
float4 tangent : TANGENT,
|
||||
float2 uv0 : TEXCOORD0,
|
||||
float2 uv1 : TEXCOORD1,
|
||||
float4 color0 : COLOR0,
|
||||
) : SV_Target0 {
|
||||
IBRDF brdf = pcb.material.GetBRDF(uv0, position.xyz, normal.xyz, tangent, color0);
|
||||
|
||||
float3 N = pcb.material.getNormal(position.xyz, normal.xyz, tangent, texCoord0);
|
||||
float2 metalRough = pcb.material.getMetalRough(texCoord0);
|
||||
float3 view_dir = normalize(pfd.camera.position.xyz - position.xyz);
|
||||
|
||||
float4 albedo = pcb.material.getAlbedo(texCoord0, vertexColor0);
|
||||
float3 viewDir = normalize(position.xyz - pfd.camera.position.xyz);
|
||||
float3 point_contrib = 0.0f.xxx;
|
||||
for (int i = 0; i < pfd.lightData.pointLightCount; ++i) {
|
||||
PointLight point_light = pfd.lightData.pointLights[i];
|
||||
|
||||
float3 pointContrib = GetPointLightInfluence(albedo.rgb, metalRough, position.xyz, N);
|
||||
float3 dirContrib = GetDirectionalLightInfluence(albedo.rgb, metalRough, position.xyz, N);
|
||||
float3 light_dir = float3(point_light.position) - position.xyz;
|
||||
float light_dist = length(light_dir);
|
||||
|
||||
return float4(pcb.material.getEmissive(texCoord0) + pointContrib + dirContrib, 1.0f);
|
||||
if (light_dist > point_light.range)
|
||||
continue;
|
||||
|
||||
light_dir /= light_dist; // Normalization
|
||||
|
||||
float attenuation = 1.0f / (light_dist * light_dist); // TODO: Controlled Attenuation
|
||||
float3 radiance = point_light.color * attenuation;
|
||||
|
||||
point_contrib += brdf.Evaluate(radiance, view_dir, light_dir);
|
||||
}
|
||||
|
||||
float3 dir_contrib = 0.0f.xxx;
|
||||
for (int i = 0; i < pfd.lightData.dirLightCount; ++i) {
|
||||
DirectionalLight dir_light = pfd.lightData.dirLights[i];
|
||||
dir_contrib += brdf.Evaluate(dir_light.color, view_dir, -normalize(dir_light.direction));
|
||||
}
|
||||
|
||||
return float4(pcb.material.GetEmissive(uv0) + point_contrib + dir_contrib, 1.0f);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,107 +1,93 @@
|
|||
public static const float PI = 3.14159265f;
|
||||
|
||||
float TrowbridgeReitzGGX(float3 normal, float3 halfway, float roughness)
|
||||
public float TrowbridgeReitzGGX(float3 normal, float3 halfway, float roughness)
|
||||
{
|
||||
float alpha = roughness * roughness;
|
||||
float alpha2 = alpha * alpha;
|
||||
float nDotH = max(dot(normal, halfway), 0.0f);
|
||||
float nDotH2 = nDotH * nDotH;
|
||||
float alpha = roughness * roughness;
|
||||
float alpha2 = alpha * alpha;
|
||||
float n_dot_h = max(dot(normal, halfway), 0.0f);
|
||||
float n_dot_h_2 = n_dot_h * n_dot_h;
|
||||
|
||||
float numerator = alpha2;
|
||||
float denominator = nDotH2 * (alpha2 - 1.0f) + 1.0f;
|
||||
denominator = PI * denominator * denominator;
|
||||
float numerator = alpha2;
|
||||
float denominator = n_dot_h_2 * (alpha2 - 1.0f) + 1.0f;
|
||||
denominator = PI * denominator * denominator;
|
||||
|
||||
return numerator / denominator;
|
||||
}
|
||||
|
||||
float GeometrySchlickGGX(float nDotV, float roughness)
|
||||
public float GeometrySchlickGGX(float n_dot_v, float roughness)
|
||||
{
|
||||
float r = roughness + 1.0f;
|
||||
float k = (r * r) / 8.0f;
|
||||
float r = roughness + 1.0f;
|
||||
float k = (r * r) / 8.0f;
|
||||
|
||||
float numerator = nDotV;
|
||||
float denominator = nDotV * (1.0f - k) + k;
|
||||
float numerator = n_dot_v;
|
||||
float denominator = n_dot_v * (1.0f - k) + k;
|
||||
|
||||
return numerator / denominator;
|
||||
}
|
||||
|
||||
float GeometrySmith(float nDotV, float nDotL, float roughness)
|
||||
public float GeometrySmith(float n_dot_v, float n_dot_l, float roughness)
|
||||
{
|
||||
float ggx1 = GeometrySchlickGGX(nDotV, roughness);
|
||||
float ggx2 = GeometrySchlickGGX(nDotL, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(n_dot_v, roughness);
|
||||
float ggx2 = GeometrySchlickGGX(n_dot_l, roughness);
|
||||
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Schlick%27s_approximation
|
||||
float3 FresnelSchlick(float cosine, float3 f_0)
|
||||
public float3 FresnelSchlick(float cosine, float3 f_0)
|
||||
{
|
||||
return f_0 + (1.0f - f_0) * pow(clamp(1.0f - cosine, 0.0f, 1.0f), 5.0f); // Clamp to avoid artifacts.
|
||||
}
|
||||
|
||||
// Sebastian Lagarde
|
||||
float3 FresnelSchlickRoughness(float cosine, float3 f_0, float roughness)
|
||||
public float3 FresnelSchlickRoughness(float cosine, float3 f_0, float roughness)
|
||||
{
|
||||
return f_0 + (max((1.0f - roughness).xxx, f_0) - f_0) * pow(clamp(1.0f - cosine, 0.0f, 1.0f), 5.0f); // Clamp to avoid artifacts.
|
||||
}
|
||||
|
||||
float3 GetPBRContrib(
|
||||
float3 albedo,
|
||||
float3 radiance,
|
||||
float3 viewDir,
|
||||
float3 normal,
|
||||
float3 lightDir,
|
||||
float2 metalRough,
|
||||
float3 f_0)
|
||||
{
|
||||
float3 halfway = normalize(viewDir + lightDir);
|
||||
|
||||
float cosineFactor = max(dot(halfway, viewDir), 0.0f);
|
||||
float nDotV = max(dot(normal, viewDir), 0.0f);
|
||||
float nDotL = max(dot(normal, lightDir), 0.0f);
|
||||
|
||||
float normalDistribution = TrowbridgeReitzGGX(normal, halfway, metalRough.y);
|
||||
float geometry = GeometrySmith(nDotV, nDotL, metalRough.y);
|
||||
float3 fresnel = FresnelSchlickRoughness(cosineFactor, f_0, metalRough.y);
|
||||
|
||||
float3 numerator = (normalDistribution * geometry) * fresnel;
|
||||
float denominator = 4.0f * nDotV * nDotL;
|
||||
float3 specular = numerator / (denominator + 0.00001f);
|
||||
|
||||
float3 kSpecular = fresnel;
|
||||
float3 kDiffuse = 1.0f - kSpecular;
|
||||
|
||||
kDiffuse *= 1.0f - metalRough.x;
|
||||
|
||||
return nDotL * radiance * (kDiffuse * albedo / PI + specular);
|
||||
public interface IBRDF {
|
||||
public float3 Evaluate(float3 radiance, float3 view_dir, float3 ligth_dir);
|
||||
}
|
||||
|
||||
public struct PointLight {
|
||||
public float3 position;
|
||||
public float range;
|
||||
public float3 color;
|
||||
float attenuation;
|
||||
public struct BRDFCookTorranceGGX : IBRDF {
|
||||
float3 m_albedo;
|
||||
float m_metallic;
|
||||
float3 m_normal;
|
||||
float m_roughness;
|
||||
float3 m_f0;
|
||||
|
||||
public float3 getInfluence(float3 albedo, float2 metalRough, float3 viewDir, float3 worldPosition, float3 normal, float3 f_0) {
|
||||
|
||||
float3 lightDir = float3(position) - worldPosition;
|
||||
float lightDistance = length(lightDir);
|
||||
|
||||
if (lightDistance > range)
|
||||
return 0.0f.xxx;
|
||||
|
||||
lightDir /= lightDistance; // Normalization
|
||||
|
||||
// Color Unpack
|
||||
//float R = (Light.Color & 0xFF000000) >> 24;
|
||||
//float G = (Light.Color & 0x00FF0000) >> 16;
|
||||
//float B = (Light.Color & 0x0000FF00) >> 8;
|
||||
|
||||
//float3 LightColor = Light.Intensity * float3(R, G, B) * 0.00392156862f; // 0.00392156862 = 1/255
|
||||
|
||||
let attenuation_ = attenuation / (lightDistance * lightDistance);
|
||||
let radiance = color * attenuation_;
|
||||
|
||||
return GetPBRContrib(albedo, radiance, viewDir, normal, lightDir, metalRough, f_0);
|
||||
public __init(float3 albedo, float metallic, float3 normal, float roughness, float3 f0) {
|
||||
m_albedo = albedo;
|
||||
m_metallic = metallic;
|
||||
m_normal = normal;
|
||||
m_roughness = roughness;
|
||||
m_f0 = f0;
|
||||
}
|
||||
};
|
||||
|
||||
public float3 Evaluate(
|
||||
float3 radiance,
|
||||
float3 view_dir,
|
||||
float3 light_dir)
|
||||
{
|
||||
float3 halfway = normalize(view_dir + light_dir);
|
||||
|
||||
float cosine_factor = max(dot(halfway, view_dir), 0.0f);
|
||||
float n_dot_v = max(dot(m_normal, view_dir), 0.0f);
|
||||
float n_dot_l = max(dot(m_normal, light_dir), 0.0f);
|
||||
|
||||
float normal_dist = TrowbridgeReitzGGX(m_normal, halfway, m_roughness);
|
||||
float geometry = GeometrySmith(n_dot_v, n_dot_l, m_roughness);
|
||||
float3 fresnel = FresnelSchlickRoughness(cosine_factor, m_f0, m_roughness);
|
||||
|
||||
float3 numerator = (normal_dist * geometry) * fresnel;
|
||||
float denominator = 4.0f * n_dot_v * n_dot_l;
|
||||
float3 specular = numerator / (denominator + 0.00001f);
|
||||
|
||||
float3 k_specular = fresnel;
|
||||
float3 k_diffuse = 1.0f.xxx - k_specular;
|
||||
|
||||
k_diffuse *= 1.0f - m_metallic;
|
||||
|
||||
return n_dot_l * radiance * (k_diffuse * m_albedo / PI + specular);
|
||||
}
|
||||
}
|
||||
|
|
@ -507,15 +507,15 @@ uint32_t ProcessMaterial( RenderDevice* render_device, Model* model, cgltf_mater
|
|||
|
||||
uint32_t const material_idx = static_cast<uint32_t>( model->materials.size() );
|
||||
model->materials.push_back( {
|
||||
sampler,
|
||||
base_color_factor,
|
||||
emissive_factor,
|
||||
base_color_texture,
|
||||
normal_texture,
|
||||
metal_rough_texture,
|
||||
emissive_texture,
|
||||
roughness,
|
||||
metallic,
|
||||
.sampler = sampler,
|
||||
.baseColor = base_color_factor,
|
||||
.emission = emissive_factor,
|
||||
.albedoTextureID = base_color_texture,
|
||||
.normalTextureID = normal_texture,
|
||||
.metalRoughTextureID = metal_rough_texture,
|
||||
.emissiveTextureID = emissive_texture,
|
||||
.metallic = metallic,
|
||||
.roughness = roughness,
|
||||
} );
|
||||
|
||||
return material_idx;
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ struct Material
|
|||
TextureID normalTextureID;
|
||||
TextureID metalRoughTextureID;
|
||||
TextureID emissiveTextureID;
|
||||
float roughness = 1.0f;
|
||||
float metallic = 1.0f;
|
||||
float roughness = 1.0f;
|
||||
|
||||
[[nodiscard]] bool IsNull() const
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue