diff --git a/Effects/PBREffect.cs b/Effects/PBREffect.cs index 852bde2..5920c2e 100644 --- a/Effects/PBREffect.cs +++ b/Effects/PBREffect.cs @@ -45,12 +45,10 @@ namespace Smuggler public class PBREffect : Effect { EffectParameter worldParam; - EffectParameter viewParam; - EffectParameter projectionParam; EffectParameter worldViewProjectionParam; EffectParameter worldInverseTransposeParam; - EffectParameter baseColorTextureParam; + EffectParameter albedoTextureParam; EffectParameter normalTextureParam; EffectParameter emissionTextureParam; EffectParameter occlusionTextureParam; @@ -105,7 +103,6 @@ namespace Smuggler set { view = value; - viewParam.SetValue(view); Matrix.Multiply(ref world, ref view, out Matrix worldView); Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj); @@ -122,7 +119,6 @@ namespace Smuggler set { projection = value; - projectionParam.SetValue(projection); Matrix.Multiply(ref world, ref view, out Matrix worldView); Matrix.Multiply(ref worldView, ref projection, out Matrix worldViewProj); @@ -176,10 +172,10 @@ namespace Smuggler } } - public Texture2D BaseColourTexture + public Texture2D AlbedoTexture { - get { return baseColorTextureParam.GetValueTexture2D(); } - set { baseColorTextureParam.SetValue(value); } + get { return albedoTextureParam.GetValueTexture2D(); } + set { albedoTextureParam.SetValue(value); } } public Texture2D NormalTexture @@ -252,7 +248,7 @@ namespace Smuggler Lights[i] = cloneSource.Lights[i]; } - BaseColourTexture = cloneSource.BaseColourTexture; + AlbedoTexture = cloneSource.AlbedoTexture; NormalTexture = cloneSource.NormalTexture; EmissionTexture = cloneSource.EmissionTexture; OcclusionTexture = cloneSource.OcclusionTexture; @@ -281,12 +277,10 @@ namespace Smuggler void CacheEffectParameters(PBREffect cloneSource) { worldParam = Parameters["World"]; - viewParam = Parameters["View"]; - projectionParam = Parameters["Projection"]; worldViewProjectionParam = Parameters["WorldViewProjection"]; worldInverseTransposeParam = Parameters["WorldInverseTranspose"]; - baseColorTextureParam = Parameters["BaseColorTexture"]; + albedoTextureParam = Parameters["AlbedoTexture"]; normalTextureParam = Parameters["NormalTexture"]; emissionTextureParam = Parameters["EmissionTexture"]; occlusionTextureParam = Parameters["OcclusionTexture"]; @@ -298,9 +292,9 @@ namespace Smuggler lightPositionsParam = Parameters["LightPositions"]; lightColorsParam = Parameters["LightColors"]; - albedoParam = Parameters["Albedo"]; - metallicParam = Parameters["Metallic"]; - roughnessParam = Parameters["Roughness"]; + albedoParam = Parameters["AlbedoValue"]; + metallicParam = Parameters["MetallicValue"]; + roughnessParam = Parameters["RoughnessValue"]; aoParam = Parameters["AO"]; eyePositionParam = Parameters["EyePosition"]; diff --git a/Effects/PBREffect.fx b/Effects/PBREffect.fx index 28dd3b5..7944e13 100644 --- a/Effects/PBREffect.fx +++ b/Effects/PBREffect.fx @@ -2,18 +2,9 @@ static const float PI = 3.141592653589793; -// Transformation Matrices - -float4x4 World; -float4x4 View; -float4x4 Projection; - -float4x4 WorldViewProjection; -float4x3 WorldInverseTranspose; - // Samplers -DECLARE_TEXTURE(BaseColorTexture, 0); +DECLARE_TEXTURE(AlbedoTexture, 0); DECLARE_TEXTURE(NormalTexture, 1); DECLARE_TEXTURE(EmissionTexture, 2); DECLARE_TEXTURE(OcclusionTexture, 3); @@ -22,17 +13,28 @@ DECLARE_CUBEMAP(EnvDiffuseTexture, 8); DECLARE_TEXTURE(BrdfLutTexture, 9); DECLARE_CUBEMAP(EnvSpecularTexture, 10); -// Light Info -float3 LightPositions[4]; -float3 LightColors[4]; +BEGIN_CONSTANTS -// PBR Values -float3 Albedo; -float Metallic; -float Roughness; -float AO; + // PBR Values + float3 AlbedoValue _ps(c0) _cb(c0); + float MetallicValue _ps(c1) _cb(c1); + float RoughnessValue _ps(c2) _cb(c2); + float AO _ps(c3) _cb(c3); -float3 EyePosition; + // Light Info + float3 LightPositions[4] _ps(c4) _cb(c4); + float3 LightColors[4] _ps(c8) _cb(c8); + + float3 EyePosition _ps(c12) _cb(c12); + + float4x4 World _vs(c0) _cb(c16); + float4x4 WorldInverseTranspose _vs(c4) _cb(c20); + +MATRIX_CONSTANTS + + float4x4 WorldViewProjection _vs(c8) _cb(c0); + +END_CONSTANTS struct VertexShaderInput { @@ -43,7 +45,7 @@ struct VertexShaderInput struct PixelShaderInput { - float4 Position : SV_POSITION; + float4 Position : SV_Position; float2 TexCoord : TEXCOORD0; float3 PositionWS : TEXCOORD1; float3 NormalWS : TEXCOORD2; @@ -55,7 +57,7 @@ PixelShaderInput main_vs(VertexShaderInput input) output.PositionWS = mul(input.Position, World).xyz; output.TexCoord = input.TexCoord; - output.NormalWS = normalize(mul(input.Normal, (float3x3)WorldInverseTranspose)); + output.NormalWS = normalize(mul(input.Normal, WorldInverseTranspose)); output.Position = mul(input.Position, WorldViewProjection); return output; @@ -104,11 +106,15 @@ float GeometrySmith(float3 N, float3 V, float3 L, float roughness) // The case where we have no texture maps for any PBR data float4 None(PixelShaderInput input) : SV_TARGET { + float3 albedo = AlbedoValue; + float metallic = MetallicValue; + float roughness = RoughnessValue; + float3 N = normalize(input.NormalWS); float3 V = normalize(EyePosition - input.PositionWS); float3 F0 = float3(0.04, 0.04, 0.04); - F0 = lerp(F0, Albedo, Metallic); + F0 = lerp(F0, albedo, metallic); float3 Lo = float3(0.0, 0.0, 0.0); @@ -122,8 +128,8 @@ float4 None(PixelShaderInput input) : SV_TARGET float attenuation = 1.0 / (distance * distance); float3 radiance = LightColors[i] * attenuation; - float NDF = DistributionGGX(N, H, Roughness); - float G = GeometrySmith(N, V, L, Roughness); + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); float3 F = FresnelSchlick(max(dot(H, V), 0.0), F0); float3 numerator = NDF * G * F; @@ -133,13 +139,116 @@ float4 None(PixelShaderInput input) : SV_TARGET float3 kS = F; float3 kD = float3(1.0, 1.0, 1.0) - kS; - kD *= 1.0 - Metallic; + kD *= 1.0 - metallic; float NdotL = max(dot(N, L), 0.0); - Lo += (kD * Albedo / PI + specular) * radiance * NdotL; + Lo += (kD * albedo / PI + specular) * radiance * NdotL; } - float3 ambient = float3(0.03, 0.03, 0.03) * Albedo * AO; + float3 ambient = float3(0.03, 0.03, 0.03) * albedo * AO; + float3 color = ambient + Lo; + + color = color / (color + float3(1.0, 1.0, 1.0)); + float exposureConstant = 1.0 / 2.2; + color = pow(color, float3(exposureConstant, exposureConstant, exposureConstant)); + + return float4(color, 1.0); +} + +float4 AlbedoMapPS(PixelShaderInput input) : SV_TARGET +{ + float3 albedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord).rgb; + float metallic = MetallicValue; + float roughness = RoughnessValue; + + float3 N = normalize(input.NormalWS); + float3 V = normalize(EyePosition - input.PositionWS); + + float3 F0 = float3(0.04, 0.04, 0.04); + F0 = lerp(F0, albedo, metallic); + + float3 Lo = float3(0.0, 0.0, 0.0); + + for (int i = 0; i < 4; i++) + { + float3 lightDir = LightPositions[i] - input.PositionWS; + float3 L = normalize(lightDir); + float3 H = normalize(V + L); + + float distance = length(lightDir); + float attenuation = 1.0 / (distance * distance); + float3 radiance = LightColors[i] * attenuation; + + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + float3 F = FresnelSchlick(max(dot(H, V), 0.0), F0); + + float3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0); + float3 specular = numerator / max(denominator, 0.001); + + float3 kS = F; + float3 kD = float3(1.0, 1.0, 1.0) - kS; + + kD *= 1.0 - metallic; + + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + } + + float3 ambient = float3(0.03, 0.03, 0.03) * albedo * AO; + float3 color = ambient + Lo; + + color = color / (color + float3(1.0, 1.0, 1.0)); + float exposureConstant = 1.0 / 2.2; + color = pow(color, float3(exposureConstant, exposureConstant, exposureConstant)); + + return float4(color, 1.0); +} + +float4 AlbedoMetallicRoughnessMapPS(PixelShaderInput input) : SV_TARGET +{ + float3 albedo = SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord).rgb; + float2 metallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord).rg; + float metallic = metallicRoughness.r; + float roughness = metallicRoughness.g; + + float3 N = normalize(input.NormalWS); + float3 V = normalize(EyePosition - input.PositionWS); + + float3 F0 = float3(0.04, 0.04, 0.04); + F0 = lerp(F0, albedo, metallic); + + float3 Lo = float3(0.0, 0.0, 0.0); + + for (int i = 0; i < 4; i++) + { + float3 lightDir = LightPositions[i] - input.PositionWS; + float3 L = normalize(lightDir); + float3 H = normalize(V + L); + + float distance = length(lightDir); + float attenuation = 1.0 / (distance * distance); + float3 radiance = LightColors[i] * attenuation; + + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + float3 F = FresnelSchlick(max(dot(H, V), 0.0), F0); + + float3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0); + float3 specular = numerator / max(denominator, 0.001); + + float3 kS = F; + float3 kD = float3(1.0, 1.0, 1.0) - kS; + + kD *= 1.0 - metallic; + + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + } + + float3 ambient = float3(0.03, 0.03, 0.03) * albedo * AO; float3 color = ambient + Lo; color = color / (color + float3(1.0, 1.0, 1.0)); diff --git a/Effects/PBREffect.fxb b/Effects/PBREffect.fxb index 2a7a43f..f4d7e8f 100644 Binary files a/Effects/PBREffect.fxb and b/Effects/PBREffect.fxb differ diff --git a/Importer.cs b/Importer.cs index ff13912..64f65f7 100644 --- a/Importer.cs +++ b/Importer.cs @@ -192,13 +192,13 @@ namespace Smuggler var albedoChannel = primitive.Material.FindChannel("BaseColor"); if (albedoChannel.HasValue) { - //if (albedoChannel.Value.Texture != null) - //{ - // effect.BaseColourTexture = Texture2D.FromStream( - // graphicsDevice, - // albedoChannel.Value.Texture.PrimaryImage.Content.Open() - // ); - //} + if (albedoChannel.Value.Texture != null) + { + effect.AlbedoTexture = Texture2D.FromStream( + graphicsDevice, + albedoChannel.Value.Texture.PrimaryImage.Content.Open() + ); + } var parameter = albedoChannel.Value.Parameter; @@ -212,13 +212,13 @@ namespace Smuggler var metallicRoughnessChannel = primitive.Material.FindChannel("MetallicRoughness"); if (metallicRoughnessChannel.HasValue) { - //if (metallicRoughnessChannel.Value.Texture != null) - //{ - // effect.MetallicRoughnessTexture = Texture2D.FromStream( - // graphicsDevice, - // metallicRoughnessChannel.Value.Texture.PrimaryImage.Content.Open() - // ); - //} + if (metallicRoughnessChannel.Value.Texture != null) + { + effect.MetallicRoughnessTexture = Texture2D.FromStream( + graphicsDevice, + metallicRoughnessChannel.Value.Texture.PrimaryImage.Content.Open() + ); + } var parameter = metallicRoughnessChannel.Value.Parameter;