This commit is contained in:
sergeypdev 2024-02-21 05:25:33 +04:00
parent 73733776d8
commit e32387ca72
2 changed files with 123 additions and 23 deletions

View File

@ -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

View File

@ -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,
},
},
});