PBR!!!
This commit is contained in:
parent
73733776d8
commit
e32387ca72
@ -1,6 +1,7 @@
|
||||
#extension GL_ARB_bindless_texture : enable
|
||||
// Keep in sync with cpu
|
||||
#define MAX_POINT_LIGHTS 8
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
|
||||
// Types
|
||||
struct Light {
|
||||
@ -33,7 +34,7 @@ layout(location = 6, bindless_sampler) uniform sampler2D metallic_map;
|
||||
layout(location = 7) uniform float roughness;
|
||||
layout(location = 8, bindless_sampler) uniform sampler2D roughness_map;
|
||||
|
||||
layout(location = 9) uniform float emission;
|
||||
layout(location = 9) uniform vec3 emission;
|
||||
layout(location = 10, bindless_sampler) uniform sampler2D emission_map;
|
||||
|
||||
|
||||
@ -70,9 +71,88 @@ void main() {
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
vec3 albedoColor = textureSize(albedo_map, 0) == ivec2(0) ? color : texture(albedo_map, VertexOut.uv).rgb;
|
||||
struct Material {
|
||||
vec3 albedo;
|
||||
bool metallic;
|
||||
float roughness;
|
||||
vec3 emission;
|
||||
};
|
||||
|
||||
Material evalMaterial() {
|
||||
Material result;
|
||||
result.albedo = textureSize(albedo_map, 0) == ivec2(0) ? pow(color, vec3(2.2)) : texture(albedo_map, VertexOut.uv).rgb;
|
||||
float fMetallic = textureSize(metallic_map, 0) == ivec2(0) ? metallic : texture(metallic_map, VertexOut.uv).r;
|
||||
result.metallic = fMetallic > 0.5;
|
||||
result.roughness = max(0.01, textureSize(roughness_map, 0) == ivec2(0) ? roughness : texture(roughness_map, VertexOut.uv).r);
|
||||
result.emission = textureSize(emission_map, 0) == ivec2(0) ? emission : texture(emission_map, VertexOut.uv).rgb;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3 schlickFresnel(Material mat, float LDotH) {
|
||||
vec3 f0 = vec3(0.04); // dielectric
|
||||
if (mat.metallic) {
|
||||
f0 = mat.albedo;
|
||||
}
|
||||
|
||||
return f0 + (1 - f0) * pow(1.0 - LDotH, 5);
|
||||
}
|
||||
|
||||
float geomSmith(Material mat, float DotVal) {
|
||||
float k = (mat.roughness + 1.0) * (mat.roughness + 1.0) / 8.0;
|
||||
float denom = DotVal * (1 - k) + k;
|
||||
return 1.0 / denom;
|
||||
}
|
||||
|
||||
float ggxDistribution(Material mat, float NDotH) {
|
||||
float alpha2 = mat.roughness * mat.roughness * mat.roughness * mat.roughness;
|
||||
float d = (NDotH * NDotH) * (alpha2 - 1) + 1;
|
||||
return alpha2 / (PI * d * d);
|
||||
}
|
||||
|
||||
float lightAttenuation(float dist, float radius) {
|
||||
float d = max(dist - radius, 0);
|
||||
|
||||
float denom = d/radius + 1;
|
||||
float att = 1 / (denom * denom);
|
||||
// TODO: cutoff
|
||||
att = max(att, 0);
|
||||
|
||||
return att;
|
||||
}
|
||||
|
||||
|
||||
vec3 microfacetModel(Material mat, Light light, vec3 P, vec3 N) {
|
||||
vec3 diffuseBrdf = vec3(0); // metallic
|
||||
if (!mat.metallic) {
|
||||
diffuseBrdf = mat.albedo;
|
||||
}
|
||||
|
||||
vec3 lightI = light.color.rgb * light.color.a;
|
||||
float lightRadius = light.vPos.w;
|
||||
vec3 L = light.vPos.xyz - P;
|
||||
float dist = length(L);
|
||||
L /= dist;
|
||||
|
||||
float att = lightAttenuation(dist, lightRadius);
|
||||
lightI *= att;
|
||||
|
||||
vec3 V = normalize(-P);
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
float NDotH = dot(N, H);
|
||||
float LDotH = dot(L, H);
|
||||
float NDotL = max(dot(N, L), 0);
|
||||
float NDotV = dot(N, V);
|
||||
|
||||
vec3 specBrdf = 0.25 * ggxDistribution(mat, NDotH) * schlickFresnel(mat, LDotH) * geomSmith(mat, NDotL) * geomSmith(mat, NDotV);
|
||||
|
||||
return (diffuseBrdf + PI * specBrdf) * lightI * NDotL;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Material material = evalMaterial();
|
||||
|
||||
vec3 N = textureSize(normal_map, 0) == ivec2(0) ? vec3(0.5) : vec3(texture(normal_map, VertexOut.uv).xy, 0);
|
||||
N = N * 2.0 - 1.0;
|
||||
N.z = sqrt(clamp(1 - N.x * N.x - N.y * N.y, 0, 1));
|
||||
@ -82,26 +162,16 @@ void main() {
|
||||
vec3 finalColor = vec3(0);
|
||||
|
||||
for (int i = 0; i < lights_count; i++) {
|
||||
float radius = lights[i].vPos.w;
|
||||
vec3 L = lights[i].vPos.xyz - VertexOut.vPos;
|
||||
float dist = length(L);
|
||||
float d = max(dist - radius, 0);
|
||||
L /= dist;
|
||||
|
||||
float denom = d/radius + 1;
|
||||
float att = 1 / (denom * denom);
|
||||
// TODO: cutoff
|
||||
att = max(att, 0);
|
||||
|
||||
float ndotl = max(dot(L, N), 0);
|
||||
|
||||
finalColor += ndotl * lights[i].color.w * lights[i].color.xyz * att * albedoColor;
|
||||
finalColor += microfacetModel(material, lights[i], VertexOut.vPos, N);
|
||||
}
|
||||
|
||||
// finalColor += microfacetModel(material, Light(vec4(VertexOut.vPos + N, 0.01), vec4(1, 1, 1, 10)), VertexOut.vPos, N);
|
||||
|
||||
FragColor = vec4(finalColor, 1.0f);
|
||||
|
||||
float gamma = 2.2;
|
||||
FragColor.rgb = pow(FragColor.rgb, vec3(1.0/gamma));
|
||||
}
|
||||
|
||||
|
||||
#endif // FRAGMNET_SHADER
|
||||
|
42
src/game.zig
42
src/game.zig
@ -143,14 +143,14 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
gl.viewport(0, 0, globals.g_init.width, globals.g_init.height);
|
||||
|
||||
_ = globals.g_mem.world.addEntity(.{
|
||||
.transform = .{ .pos = Vec3.new(1, 1, 0) },
|
||||
.transform = .{ .pos = Vec3.new(1.8, 1, 0) },
|
||||
.flags = .{ .point_light = true, .rotate = true },
|
||||
.point_light = .{ .color_intensity = Vec4.new(1.0, 0.3, 0.1, 100.0), .radius = 0.1 },
|
||||
.rotate = .{ .axis = Vec3.up(), .rate = 60 },
|
||||
});
|
||||
|
||||
_ = globals.g_mem.world.addEntity(.{
|
||||
.transform = .{ .pos = Vec3.new(-1, 1, 0) },
|
||||
.transform = .{ .pos = Vec3.new(-2, 1, 0) },
|
||||
.flags = .{ .point_light = true, .rotate = true },
|
||||
.point_light = .{
|
||||
.color_intensity = Vec4.new(0.2, 0.5, 1.0, 100.0),
|
||||
@ -159,10 +159,19 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
.rotate = .{ .axis = Vec3.up(), .rate = -20 },
|
||||
});
|
||||
|
||||
_ = globals.g_mem.world.addEntity(.{
|
||||
.transform = .{ .pos = Vec3.new(1, 0.5, 4) },
|
||||
.flags = .{ .point_light = true },
|
||||
.point_light = .{
|
||||
.color_intensity = Vec4.new(0.2, 0.5, 1.0, 10.0),
|
||||
.radius = 1,
|
||||
},
|
||||
});
|
||||
|
||||
// Plane
|
||||
_ = globals.g_mem.world.addEntity(.{
|
||||
.flags = .{ .mesh = true },
|
||||
.transform = .{ .scale = Vec3.one().scale(1) },
|
||||
.transform = .{ .scale = Vec3.one().scale(2) },
|
||||
.mesh = .{
|
||||
.handle = a.Meshes.plane,
|
||||
.material = .{
|
||||
@ -171,18 +180,39 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
},
|
||||
});
|
||||
|
||||
// 10 bunnies
|
||||
// 10 dielectric bunnies
|
||||
{
|
||||
for (0..10) |i| {
|
||||
_ = globals.g_mem.world.addEntity(.{
|
||||
.transform = .{ .pos = Vec3.new(@as(f32, @floatFromInt(i)) * 0.3, 0, 0) },
|
||||
.transform = .{ .pos = Vec3.new(@as(f32, @floatFromInt(i)) * 0.3 - 0.3 * 4.5, 0, 0) },
|
||||
|
||||
.flags = .{ .mesh = true },
|
||||
.mesh = .{
|
||||
.handle = a.Meshes.bunny,
|
||||
.material = .{
|
||||
.albedo_map = a.Textures.bunny_tex1,
|
||||
.normal_map = a.Textures.@"tile.norm",
|
||||
// .normal_map = a.Textures.@"tile.norm",
|
||||
.roughness = @as(f32, @floatFromInt(i)) / 10.0,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
// 10 metallic bunnies
|
||||
{
|
||||
for (0..10) |i| {
|
||||
_ = globals.g_mem.world.addEntity(.{
|
||||
.transform = .{ .pos = Vec3.new(@as(f32, @floatFromInt(i)) * 0.3 - 0.3 * 4.5, 0.3, 0) },
|
||||
|
||||
.flags = .{ .mesh = true },
|
||||
.mesh = .{
|
||||
.handle = a.Meshes.bunny,
|
||||
.material = .{
|
||||
.albedo = Vec3.new(1.000, 0.766, 0.336),
|
||||
// .albedo_map = a.Textures.bunny_tex1,
|
||||
// .normal_map = a.Textures.@"tile.norm",
|
||||
.roughness = @as(f32, @floatFromInt(i + 1)) / 10.0,
|
||||
.metallic = 1.0,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user