add normal map sampling
parent
5465b13b9d
commit
75114d77ef
|
@ -57,7 +57,7 @@ PixelShaderInput main_vs(VertexShaderInput input)
|
|||
|
||||
output.TexCoord = input.TexCoord;
|
||||
output.PositionWS = mul(input.Position, World).xyz;
|
||||
output.NormalWS = mul(input.Normal, WorldInverseTranspose);
|
||||
output.NormalWS = mul(input.Normal, (float3x3)WorldInverseTranspose).xyz;
|
||||
output.Position = mul(input.Position, WorldViewProjection);
|
||||
|
||||
return output;
|
||||
|
@ -103,6 +103,24 @@ float GeometrySmith(float3 N, float3 V, float3 L, float roughness)
|
|||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
// Easy trick to get tangent-normals to world-space to keep PBR code simplified.
|
||||
float3 GetNormalFromMap(float3 worldPos, float2 texCoords, float3 normal)
|
||||
{
|
||||
float3 tangentNormal = SAMPLE_TEXTURE(NormalTexture, texCoords).xyz * 2.0 - 1.0;
|
||||
|
||||
float3 Q1 = ddx(worldPos);
|
||||
float3 Q2 = ddy(worldPos);
|
||||
float2 st1 = ddx(texCoords);
|
||||
float2 st2 = ddy(texCoords);
|
||||
|
||||
float3 N = normalize(normal);
|
||||
float3 T = normalize(Q1*st2.y - Q2*st1.y);
|
||||
float3 B = -normalize(cross(N, T));
|
||||
float3x3 TBN = float3x3(T, B, N);
|
||||
|
||||
return normalize(mul(tangentNormal, TBN));
|
||||
}
|
||||
|
||||
// The case where we have no texture maps for any PBR data
|
||||
float4 None(PixelShaderInput input) : SV_TARGET0
|
||||
{
|
||||
|
@ -258,11 +276,63 @@ float4 AlbedoMetallicRoughnessMapPS(PixelShaderInput input) : SV_TARGET
|
|||
return float4(color, 1.0);
|
||||
}
|
||||
|
||||
float4 AlbedoMetallicRoughnessNormalMapPS(PixelShaderInput input) : SV_TARGET
|
||||
{
|
||||
float3 albedo = pow(SAMPLE_TEXTURE(AlbedoTexture, input.TexCoord), 2.2).rgb;
|
||||
float2 metallicRoughness = SAMPLE_TEXTURE(MetallicRoughnessTexture, input.TexCoord).rg;
|
||||
float metallic = metallicRoughness.r;
|
||||
float roughness = metallicRoughness.g;
|
||||
|
||||
float3 N = GetNormalFromMap(input.PositionWS, input.TexCoord, 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);
|
||||
}
|
||||
|
||||
Technique PBR
|
||||
{
|
||||
Pass Pass1
|
||||
{
|
||||
VertexShader = compile vs_3_0 main_vs();
|
||||
PixelShader = compile ps_3_0 AlbedoMetallicRoughnessMapPS();
|
||||
PixelShader = compile ps_3_0 AlbedoMetallicRoughnessNormalMapPS();
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
26
Importer.cs
26
Importer.cs
|
@ -141,19 +141,17 @@ namespace Smuggler
|
|||
|
||||
if (primitive.Material != null)
|
||||
{
|
||||
//var normalChannel = primitive.Material.FindChannel("Normal");
|
||||
//if (normalChannel.HasValue)
|
||||
//{
|
||||
// if (normalChannel.Value.Texture != null)
|
||||
// {
|
||||
// effect.NormalTexture = Texture2D.FromStream(
|
||||
// graphicsDevice,
|
||||
// normalChannel.Value.Texture.PrimaryImage.Content.Open()
|
||||
// );
|
||||
// }
|
||||
|
||||
// effect.NormalScale = normalChannel.Value.Parameter.X;
|
||||
//}
|
||||
var normalChannel = primitive.Material.FindChannel("Normal");
|
||||
if (normalChannel.HasValue)
|
||||
{
|
||||
if (normalChannel.Value.Texture != null)
|
||||
{
|
||||
effect.NormalTexture = Texture2D.FromStream(
|
||||
graphicsDevice,
|
||||
normalChannel.Value.Texture.PrimaryImage.Content.Open()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//var occlusionChannel = primitive.Material.FindChannel("Occlusion");
|
||||
//if (occlusionChannel.HasValue)
|
||||
|
@ -218,7 +216,6 @@ namespace Smuggler
|
|||
graphicsDevice,
|
||||
metallicRoughnessChannel.Value.Texture.PrimaryImage.Content.Open()
|
||||
);
|
||||
System.Console.WriteLine(effect.MetallicRoughnessTexture.Width);
|
||||
}
|
||||
|
||||
var parameter = metallicRoughnessChannel.Value.Parameter;
|
||||
|
@ -416,7 +413,6 @@ namespace Smuggler
|
|||
uint[] indices,
|
||||
Vector3[] positions
|
||||
) {
|
||||
System.Console.WriteLine("normals");
|
||||
var normals = Normals(primitive);
|
||||
var texcoords = TexCoords(primitive);
|
||||
|
||||
|
|
Loading…
Reference in New Issue