Alpha blending!
This commit is contained in:
parent
a865ea4ab7
commit
b4a2b1d728
@ -55,7 +55,7 @@ int getCSMSplit(int lightIdx, float depth) {
|
||||
// Uniforms
|
||||
layout(location = 1) uniform mat4 model;
|
||||
|
||||
layout(location = 2) uniform vec3 color;
|
||||
layout(location = 2) uniform vec4 color;
|
||||
layout(location = 3, bindless_sampler) uniform sampler2D albedo_map;
|
||||
layout(location = 4) uniform vec2 albedo_map_uv_scale = vec2(1);
|
||||
|
||||
@ -122,7 +122,7 @@ void main() {
|
||||
out vec4 FragColor;
|
||||
|
||||
struct Material {
|
||||
vec3 albedo;
|
||||
vec4 albedo;
|
||||
bool metallic;
|
||||
float roughness;
|
||||
vec3 emission;
|
||||
@ -130,7 +130,7 @@ struct Material {
|
||||
|
||||
Material evalMaterial() {
|
||||
Material result;
|
||||
result.albedo = textureSize(albedo_map, 0) == ivec2(0) ? pow(color, vec3(2.2)) : texture(albedo_map, VertexOut.uv * albedo_map_uv_scale).rgb;
|
||||
result.albedo = textureSize(albedo_map, 0) == ivec2(0) ? vec4(pow(color.rgb, vec3(2.2)), color.a) : texture(albedo_map, VertexOut.uv * albedo_map_uv_scale);
|
||||
float fMetallic = textureSize(metallic_map, 0) == ivec2(0) ? metallic : texture(metallic_map, VertexOut.uv * metallic_map_uv_scale).b;
|
||||
result.metallic = fMetallic > 0.1;
|
||||
result.roughness = max(0.01, textureSize(roughness_map, 0) == ivec2(0) ? roughness : texture(roughness_map, VertexOut.uv * roughness_map_uv_scale).g);
|
||||
@ -142,7 +142,7 @@ Material evalMaterial() {
|
||||
vec3 schlickFresnel(Material mat, float LDotH) {
|
||||
vec3 f0 = vec3(0.04); // dielectric
|
||||
if (mat.metallic) {
|
||||
f0 = mat.albedo;
|
||||
f0 = mat.albedo.rgb;
|
||||
}
|
||||
|
||||
return f0 + (1 - f0) * pow(1.0 - LDotH, 5);
|
||||
@ -193,11 +193,11 @@ float map(float value, float min1, float max1, float min2, float max2) {
|
||||
|
||||
vec3 microfacetModel(Material mat, int light_idx, Light light, vec3 P, vec3 N) {
|
||||
int csm_split_idx = getCSMSplit(light_idx, P.z);
|
||||
mat.albedo = mix(mat.albedo, csm_split_colors[csm_split_idx], 0.8);
|
||||
mat.albedo = vec4(mix(mat.albedo.rgb, csm_split_colors[csm_split_idx], 0.8), mat.albedo.a);
|
||||
|
||||
vec3 diffuseBrdf = vec3(0); // metallic
|
||||
if (!mat.metallic) {
|
||||
diffuseBrdf = mat.albedo;
|
||||
diffuseBrdf = mat.albedo.rgb;
|
||||
}
|
||||
|
||||
// 0 - means directional, 1 - means point light
|
||||
@ -303,7 +303,7 @@ void main() {
|
||||
finalColor += microfacetModel(material, i, lights[i], VertexOut.vPos, N);
|
||||
}
|
||||
|
||||
FragColor = vec4(finalColor, 1.0f);
|
||||
FragColor = vec4(finalColor, material.albedo.a);
|
||||
}
|
||||
|
||||
|
||||
|
@ -445,6 +445,35 @@ pub fn finish(self: *Render) void {
|
||||
const camera_projection = self.camera.projection();
|
||||
const view_proj = camera_projection.mul(self.camera.view_mat);
|
||||
|
||||
// Sort draw calls: opaque -> blended
|
||||
{
|
||||
const cmds = self.command_buffer[0..self.command_count];
|
||||
std.mem.sortUnstable(DrawCommand, cmds, self, struct {
|
||||
pub fn lessThan(render: *const Render, lhs: DrawCommand, rhs: DrawCommand) bool {
|
||||
const lhs_mesh = render.assetman.resolveMesh(lhs.mesh);
|
||||
const rhs_mesh = render.assetman.resolveMesh(rhs.mesh);
|
||||
const lhs_material: Material = if (lhs.material_override) |mat| mat else lhs_mesh.material;
|
||||
const rhs_material: Material = if (rhs.material_override) |mat| mat else rhs_mesh.material;
|
||||
return switch (lhs_material.blend_mode) {
|
||||
.Opaque => switch (rhs_material.blend_mode) {
|
||||
.AlphaBlend => true,
|
||||
.Opaque => false,
|
||||
},
|
||||
.AlphaBlend => switch (rhs_material.blend_mode) {
|
||||
.Opaque => false,
|
||||
.AlphaBlend => {
|
||||
const lhs_view_pos = render.camera.view_mat.mulByVec4(lhs.transform.extractTranslation().toVec4(1));
|
||||
const rhs_view_pos = render.camera.view_mat.mulByVec4(rhs.transform.extractTranslation().toVec4(1));
|
||||
|
||||
// Back to front sorting. View pos has negative Z
|
||||
return lhs_view_pos.z() < rhs_view_pos.z();
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}.lessThan);
|
||||
}
|
||||
|
||||
if (self.update_view_frustum) {
|
||||
self.camera_view_proj = view_proj;
|
||||
self.world_camera_frustum = math.Frustum.new(view_proj);
|
||||
@ -698,6 +727,9 @@ pub fn finish(self: *Render) void {
|
||||
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.mesh).program);
|
||||
gl.bindVertexArray(self.mesh_vao);
|
||||
|
||||
var switched_to_alpha_blend = false;
|
||||
gl.disable(gl.BLEND);
|
||||
|
||||
var rendered_count: usize = 0;
|
||||
for (self.command_buffer[0..self.command_count]) |*cmd| {
|
||||
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
||||
@ -710,9 +742,18 @@ pub fn finish(self: *Render) void {
|
||||
|
||||
const material: Material = if (cmd.material_override) |mat| mat else mesh.material;
|
||||
|
||||
// Opaque objects are drawn, start rendering alpha blended objects
|
||||
{
|
||||
if (material.blend_mode == .AlphaBlend and !switched_to_alpha_blend) {
|
||||
switched_to_alpha_blend = true;
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
gl.uniformMatrix4fv(Uniform.ModelMatrix.value(), 1, gl.FALSE, @ptrCast(&cmd.transform.data));
|
||||
{
|
||||
gl.uniform3fv(Uniform.Color.value(), 1, @ptrCast(&material.albedo.data));
|
||||
gl.uniform4fv(Uniform.Color.value(), 1, @ptrCast(&material.albedo.data));
|
||||
|
||||
const albedo_map = self.assetman.resolveTexture(material.albedo_map);
|
||||
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
|
||||
@ -775,6 +816,8 @@ pub fn finish(self: *Render) void {
|
||||
);
|
||||
}
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
|
||||
// Debug stuff
|
||||
{
|
||||
gl.polygonMode(gl.FRONT_AND_BACK, gl.LINE);
|
||||
|
@ -3,6 +3,7 @@ const builtin = @import("builtin");
|
||||
const Handle = @import("assets").Handle;
|
||||
const za = @import("zalgebra");
|
||||
const Vec3 = za.Vec3;
|
||||
const Vec4 = za.Vec4;
|
||||
pub const Entity = @import("entity.zig").Entity;
|
||||
|
||||
pub const native_endian = builtin.cpu.arch.endian();
|
||||
@ -366,8 +367,12 @@ test "write and read scene" {
|
||||
}
|
||||
|
||||
pub const Material = extern struct {
|
||||
// TODO: rgba
|
||||
albedo: Vec3 = Vec3.one(),
|
||||
pub const BlendMode = enum(u8) {
|
||||
Opaque,
|
||||
AlphaBlend,
|
||||
};
|
||||
|
||||
albedo: Vec4 = Vec4.one(),
|
||||
albedo_map: Handle.Texture = .{},
|
||||
normal_map: Handle.Texture = .{},
|
||||
metallic: f32 = 0,
|
||||
@ -376,6 +381,7 @@ pub const Material = extern struct {
|
||||
roughness_map: Handle.Texture = .{},
|
||||
emission: Vec3 = Vec3.zero(),
|
||||
emission_map: Handle.Texture = .{},
|
||||
blend_mode: BlendMode = .Opaque,
|
||||
|
||||
pub fn fromBuffer(buf: []const u8) Material {
|
||||
const mat: *align(1) const Material = @ptrCast(buf);
|
||||
|
@ -230,6 +230,8 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
.mesh = .{
|
||||
.handle = a.Meshes.plane.Plane,
|
||||
.material = .{
|
||||
.blend_mode = .AlphaBlend,
|
||||
.albedo = Vec4.new(1, 1, 1, 0.5),
|
||||
.normal_map = a.Textures.@"tile.norm",
|
||||
},
|
||||
.override_material = true,
|
||||
@ -265,7 +267,8 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
.mesh = .{
|
||||
.handle = a.Meshes.bunny.BunnyStanfordUVUnwrapped_res1_bun_zipper_res1,
|
||||
.material = .{
|
||||
.albedo = Vec3.new(1.000, 0.766, 0.336),
|
||||
.blend_mode = .AlphaBlend,
|
||||
.albedo = Vec4.new(1.000, 0.766, 0.336, 0.5),
|
||||
// .albedo_map = a.Textures.bunny_tex1,
|
||||
// .normal_map = a.Textures.@"tile.norm",
|
||||
.roughness = @as(f32, @floatFromInt(i + 1)) / 10.0,
|
||||
@ -464,7 +467,7 @@ export fn game_update() bool {
|
||||
} else if (ent.data.flags.point_light) {
|
||||
gmem.render.draw(.{
|
||||
.mesh = a.Meshes.sphere.Icosphere,
|
||||
.material_override = .{ .albedo = Vec3.zero(), .emission = ent.data.light.premultipliedColor() },
|
||||
.material_override = .{ .albedo = Vec4.new(0, 0, 0, 1), .emission = ent.data.light.premultipliedColor() },
|
||||
.transform = ent.globalMatrix(&gmem.world).*,
|
||||
});
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ const Vector2 = formats.Vector2;
|
||||
const Vector3 = formats.Vector3;
|
||||
const za = @import("zalgebra");
|
||||
const Vec3 = za.Vec3;
|
||||
const Vec4 = za.Vec4;
|
||||
const Mat4 = za.Mat4;
|
||||
const c = @cImport({
|
||||
@cInclude("assimp/cimport.h");
|
||||
@ -203,7 +204,7 @@ fn processScene(allocator: std.mem.Allocator, input: []const u8, output_dir: std
|
||||
var base_color: c.aiColor4D = .{};
|
||||
if (c.aiGetMaterialColor(material, AI_MATKEY_BASE_COLOR, 0, 0, &base_color) == c.aiReturn_SUCCESS) {
|
||||
// TODO: rgba
|
||||
mat_output.albedo = Vec3.new(base_color.r, base_color.g, base_color.b);
|
||||
mat_output.albedo = Vec4.new(base_color.r, base_color.g, base_color.b, base_color.a);
|
||||
}
|
||||
|
||||
if (c.aiGetMaterialTextureCount(material, c.aiTextureType_BASE_COLOR) > 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user