Bring back translucent rendering, try to optimize shaders, try figuring out which materials are masked
This commit is contained in:
parent
637ad85979
commit
8031b77c8a
@ -55,8 +55,8 @@ layout(location = 2) in vec2 aUV;
|
||||
layout(location = 3) in vec3 aTangent;
|
||||
|
||||
void main() {
|
||||
DrawID = gl_DrawID;
|
||||
mat4 model = draw_data[gl_DrawID].transform;
|
||||
DrawID = gl_BaseInstance + gl_InstanceID;
|
||||
mat4 model = draw_data[DrawID].transform;
|
||||
mat4 viewModel = view * model;
|
||||
vec4 vPos = viewModel * vec4(aPos.xyz, 1.0);
|
||||
gl_Position = projection * vPos;
|
||||
@ -126,13 +126,6 @@ layout(std430, binding = 2) readonly buffer Materials {
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
struct EvalMaterial {
|
||||
vec4 albedo;
|
||||
float metallic;
|
||||
float roughness;
|
||||
vec3 emission;
|
||||
};
|
||||
|
||||
int getShadowMapIndex(int lightIdx) {
|
||||
return int(lights[lightIdx].params.z);
|
||||
}
|
||||
@ -153,39 +146,44 @@ int getCSMSplit(int lightIdx, float depth) {
|
||||
return CSM_SPLITS - 1;
|
||||
}
|
||||
|
||||
EvalMaterial evalMaterial() {
|
||||
EvalMaterial result;
|
||||
int materialIdx = draw_data[DrawID].materialIdx;
|
||||
result.albedo = textureSize(materials[materialIdx].albedo_map, 0) == ivec2(0) ? vec4(pow(materials[materialIdx].albedo.rgb, vec3(2.2)), materials[materialIdx].albedo.a) : texture(materials[materialIdx].albedo_map, VertexOut.uv * materials[materialIdx].albedo_map_uv_scale);
|
||||
result.metallic = textureSize(materials[materialIdx].metallic_map, 0) == ivec2(0) ? materials[materialIdx].metallic : texture(materials[materialIdx].metallic_map, VertexOut.uv * materials[materialIdx].metallic_map_uv_scale).b;
|
||||
result.roughness = max(0.01, textureSize(materials[materialIdx].roughness_map, 0) == ivec2(0) ? materials[materialIdx].roughness : texture(materials[materialIdx].roughness_map, VertexOut.uv * materials[materialIdx].roughness_map_uv_scale).g);
|
||||
result.emission = textureSize(materials[materialIdx].emission_map, 0) == ivec2(0) ? materials[materialIdx].emission : texture(materials[materialIdx].emission_map, VertexOut.uv * materials[materialIdx].emission_map_uv_scale).rgb;
|
||||
|
||||
return result;
|
||||
vec4 getAlbedo(int materialIdx) {
|
||||
return textureSize(materials[materialIdx].albedo_map, 0) == ivec2(0) ? vec4(pow(materials[materialIdx].albedo.rgb, vec3(2.2)), materials[materialIdx].albedo.a) : texture(materials[materialIdx].albedo_map, VertexOut.uv * materials[materialIdx].albedo_map_uv_scale);
|
||||
}
|
||||
|
||||
vec3 schlickFresnel(EvalMaterial mat, float NDotV) {
|
||||
vec3 f0 = mix(vec3(0.04), mat.albedo.rgb, mat.metallic);
|
||||
float getRoughness(int materialIdx) {
|
||||
return max(0.01, textureSize(materials[materialIdx].roughness_map, 0) == ivec2(0) ? materials[materialIdx].roughness : texture(materials[materialIdx].roughness_map, VertexOut.uv * materials[materialIdx].roughness_map_uv_scale).g);
|
||||
}
|
||||
|
||||
float getMetallic(int materialIdx) {
|
||||
return textureSize(materials[materialIdx].metallic_map, 0) == ivec2(0) ? materials[materialIdx].metallic : texture(materials[materialIdx].metallic_map, VertexOut.uv * materials[materialIdx].metallic_map_uv_scale).b;
|
||||
}
|
||||
|
||||
vec3 getEmission(int materialIdx) {
|
||||
return textureSize(materials[materialIdx].emission_map, 0) == ivec2(0) ? materials[materialIdx].emission : texture(materials[materialIdx].emission_map, VertexOut.uv * materials[materialIdx].emission_map_uv_scale).rgb;
|
||||
}
|
||||
|
||||
vec3 schlickFresnel(int matIdx, float NDotV) {
|
||||
vec3 f0 = mix(vec3(0.04), getAlbedo(matIdx).rgb, getMetallic(matIdx));
|
||||
|
||||
return f0 + (1.0 - f0) * pow(1.0 - NDotV, 5.0);
|
||||
}
|
||||
|
||||
vec3 schlickFresnelRoughness(EvalMaterial mat, float NDotV) {
|
||||
vec3 f0 = mix(vec3(0.04), mat.albedo.rgb, mat.metallic);
|
||||
vec3 schlickFresnelRoughness(int matIdx, float NDotV) {
|
||||
vec3 f0 = mix(vec3(0.04), getAlbedo(matIdx).rgb, getMetallic(matIdx));
|
||||
|
||||
return f0 + (max(vec3(1.0 - mat.roughness), f0) - f0) * pow(1.0 - NDotV, 5.0);
|
||||
return f0 + (max(vec3(1.0 - getRoughness(matIdx)), f0) - f0) * pow(1.0 - NDotV, 5.0);
|
||||
}
|
||||
|
||||
const float eps = 0.0001;
|
||||
|
||||
float geomSmith(EvalMaterial mat, float DotVal) {
|
||||
float k = ((mat.roughness + 1.0) * (mat.roughness + 1.0)) / 8.0;
|
||||
float geomSmith(int matIdx, float DotVal) {
|
||||
float k = ((getRoughness(matIdx) + 1.0) * (getRoughness(matIdx) + 1.0)) / 8.0;
|
||||
float denom = DotVal * (1 - k) + k;
|
||||
return DotVal / denom;
|
||||
}
|
||||
|
||||
float ggxDistribution(EvalMaterial mat, float NDotH) {
|
||||
float a = mat.roughness * mat.roughness;
|
||||
float ggxDistribution(int matIdx, float NDotH) {
|
||||
float a = getRoughness(matIdx) * getRoughness(matIdx);
|
||||
float alpha2 = a * a;
|
||||
float NDotH2 = NDotH * NDotH;
|
||||
float nom = alpha2;
|
||||
@ -223,12 +221,12 @@ float map(float value, float min1, float max1, float min2, float max2) {
|
||||
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
||||
}
|
||||
|
||||
vec3 microfacetModel(EvalMaterial mat, int light_idx, vec3 P, vec3 N) {
|
||||
vec3 microfacetModel(int matIdx, int light_idx, vec3 P, vec3 N) {
|
||||
// Light light = lights[light_idx];
|
||||
|
||||
vec3 diffuseBrdf = vec3(0); // metallic
|
||||
if (mat.metallic < 1.0) {
|
||||
diffuseBrdf = mat.albedo.rgb / PI;
|
||||
if (getMetallic(matIdx) < 1.0) {
|
||||
diffuseBrdf = getAlbedo(matIdx).rgb / PI;
|
||||
}
|
||||
|
||||
// 0 - means directional, 1 - means point light
|
||||
@ -311,20 +309,20 @@ vec3 microfacetModel(EvalMaterial mat, int light_idx, vec3 P, vec3 N) {
|
||||
}
|
||||
shadow_mult = clamp(shadow_mult, 0.0, 1.0);
|
||||
|
||||
vec3 F = schlickFresnelRoughness(mat, NDotV);
|
||||
vec3 specBrdf = F * ggxDistribution(mat, NDotH) * geomSmith(mat, NDotV) * geomSmith(mat, NDotL);
|
||||
vec3 F = schlickFresnelRoughness(matIdx, NDotV);
|
||||
vec3 specBrdf = F * (ggxDistribution(matIdx, NDotH) * geomSmith(matIdx, NDotV) * geomSmith(matIdx, NDotL));
|
||||
specBrdf /= 4.0 * NDotL * NDotV + 0.0001;
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = vec3(1.0) - kS;
|
||||
kD *= 1.0 - mat.metallic;
|
||||
kD *= 1.0 - getMetallic(matIdx);
|
||||
|
||||
return (kD * diffuseBrdf + specBrdf) * lightI * NDotL * shadow_mult;
|
||||
return (kD * diffuseBrdf + specBrdf) * lightI * (NDotL * shadow_mult);
|
||||
}
|
||||
|
||||
vec3 ibl(EvalMaterial mat, vec3 N, vec3 V) {
|
||||
vec3 ibl(int matIdx, vec3 N, vec3 V) {
|
||||
float NDotV = max(dot(N, V), 0.0);
|
||||
vec3 F = schlickFresnelRoughness(mat, NDotV);
|
||||
vec3 F = schlickFresnelRoughness(matIdx, NDotV);
|
||||
vec3 kS = F;
|
||||
vec3 kD = 1.0 - kS;
|
||||
|
||||
@ -333,19 +331,18 @@ vec3 ibl(EvalMaterial mat, vec3 N, vec3 V) {
|
||||
float ambient_spec = dot(R, VertexOut.vUp) * 0.5 + 0.5;
|
||||
|
||||
vec3 irradiance = vec3(1.0, 0.9764705882352941, 0.9921568627450981) * 79 * ambient_diff;
|
||||
vec3 diffuse = irradiance * mat.albedo.rgb;
|
||||
vec3 diffuse = irradiance * getAlbedo(matIdx).rgb;
|
||||
|
||||
vec3 reflectedColor = vec3(0.9, 0.9064705882352941, 0.9921568627450981) * 79 * ambient_spec;
|
||||
vec2 envBRDF = textureLod(brdfLut, vec2(NDotV, mat.roughness), 0).rg;
|
||||
vec2 envBRDF = textureLod(brdfLut, vec2(NDotV, getRoughness(matIdx)), 0).rg;
|
||||
vec3 specular = reflectedColor * (F * envBRDF.x + envBRDF.y);
|
||||
return kD * diffuse + specular;
|
||||
}
|
||||
|
||||
void main() {
|
||||
int materialIdx = draw_data[DrawID].materialIdx;
|
||||
sampler2D normal_map = materials[materialIdx].normal_map;
|
||||
vec2 normal_map_uv_scale = materials[materialIdx].normal_map_uv_scale;
|
||||
EvalMaterial material = evalMaterial();
|
||||
int matIdx = draw_data[DrawID].materialIdx;
|
||||
sampler2D normal_map = materials[matIdx].normal_map;
|
||||
vec2 normal_map_uv_scale = materials[matIdx].normal_map_uv_scale;
|
||||
|
||||
vec3 N = textureSize(normal_map, 0) == ivec2(0) ? vec3(0.5) : vec3(texture(normal_map, VertexOut.uv * normal_map_uv_scale).xy, 0);
|
||||
N = N * 2.0 - 1.0;
|
||||
@ -356,18 +353,17 @@ void main() {
|
||||
|
||||
vec3 finalColor = vec3(0);
|
||||
|
||||
// int n_lights = clamp(int(lights_count), 0, MAX_POINT_LIGHTS);
|
||||
for (int i = 0; i < MAX_POINT_LIGHTS; i++) {
|
||||
if (i >= lights_count) break;
|
||||
finalColor += microfacetModel(material, i, VertexOut.vPos, N);
|
||||
int n_lights = clamp(int(lights_count), 0, MAX_POINT_LIGHTS);
|
||||
for (int i = 0; i < n_lights; i++) {
|
||||
finalColor += microfacetModel(matIdx, i, VertexOut.vPos, N);
|
||||
}
|
||||
|
||||
vec3 V = normalize(-VertexOut.vPos);
|
||||
// ambient
|
||||
finalColor += ibl(material, N, V);
|
||||
finalColor += material.emission;
|
||||
finalColor += ibl(matIdx, N, V);
|
||||
finalColor += getEmission(matIdx);
|
||||
|
||||
FragColor = vec4(finalColor, material.albedo.a);
|
||||
FragColor = vec4(finalColor, getAlbedo(matIdx).a);
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,9 +69,9 @@ vec3 linearToSRGB(vec3 color) {
|
||||
|
||||
void main() {
|
||||
vec3 hdr_color = texture(screen_sampler, VertexOut.uv).rgb;
|
||||
hdr_color = ACESFitted(hdr_color * 0.008);
|
||||
hdr_color = ACESFitted(hdr_color * 0.02);
|
||||
|
||||
FragColor.rgb = linearToSRGB(hdr_color);
|
||||
FragColor.rgb = hdr_color;
|
||||
FragColor.a = 1;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ layout(std430, binding = 3) readonly buffer DrawCmdDatas {
|
||||
layout(location = 0) in vec3 aPos;
|
||||
|
||||
void main() {
|
||||
mat4 model = draw_data[gl_DrawID].transform;
|
||||
mat4 model = draw_data[gl_BaseInstance + gl_InstanceID].transform;
|
||||
mat4 viewModel = view * model;
|
||||
vec4 vPos = viewModel * vec4(aPos.xyz, 1.0);
|
||||
gl_Position = projection * vPos;
|
||||
|
@ -429,9 +429,9 @@ pub const LightCommand = union(LightKind) {
|
||||
};
|
||||
|
||||
const DrawCommandKey = packed struct {
|
||||
transparent: u1 = 0,
|
||||
distance: u15 = 0,
|
||||
mesh: u16 = 0,
|
||||
distance: u15 = 0,
|
||||
transparent: u1 = 0,
|
||||
};
|
||||
|
||||
pub fn drawLight(self: *Render, cmd: LightCommand) void {
|
||||
@ -449,7 +449,7 @@ pub fn draw(self: *Render, cmd: DrawCommand) void {
|
||||
const dist: u15 = @intFromFloat(std.math.clamp(view_origin.distance(cmd.transform.extractTranslation()) / max_value, 0.0, max_value));
|
||||
const key = DrawCommandKey{
|
||||
.transparent = if (material.blend_mode == .AlphaBlend) 1 else 0,
|
||||
.distance = if (material.blend_mode == .AlphaBlend) ~dist else dist, // TODO: calculate distance. Opaque should be front to back, transparent back to front
|
||||
.distance = if (material.blend_mode == .AlphaBlend) dist else dist, // TODO: calculate distance. Opaque should be front to back, transparent back to front
|
||||
.mesh = @intCast(cmd.mesh.id % std.math.maxInt(u16)),
|
||||
};
|
||||
self.command_buffer[self.command_count].key = key;
|
||||
@ -547,6 +547,20 @@ pub fn finish(self: *Render) void {
|
||||
defer zoneSort.deinit();
|
||||
|
||||
self.sortCommands(self.command_buffer[0..self.command_count]);
|
||||
|
||||
// Sorting validation
|
||||
if (false) {
|
||||
var alpha = false;
|
||||
for (self.command_buffer[0..self.command_count]) |cmd| {
|
||||
if (!alpha and cmd.key.transparent == 1) {
|
||||
alpha = true;
|
||||
}
|
||||
|
||||
if (alpha and cmd.key.transparent == 0) {
|
||||
std.log.err("WRONG SORTING!\n", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.update_view_frustum) {
|
||||
@ -801,8 +815,7 @@ pub fn finish(self: *Render) void {
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
const switched_to_alpha_blend = false;
|
||||
gl.disable(gl.BLEND);
|
||||
var switched_to_alpha_blend = false;
|
||||
|
||||
var draw_indirect_cmds = self.frame_arena.alloc(DrawIndirectCmd, MAX_DRAW_COMMANDS) catch @panic("OOM");
|
||||
var draw_cmd_data = self.frame_arena.alloc(DrawCommandData, MAX_DRAW_COMMANDS) catch @panic("OOM");
|
||||
@ -818,6 +831,7 @@ pub fn finish(self: *Render) void {
|
||||
defer gl.deleteBuffers(1, &draw_cmd_data_buf);
|
||||
|
||||
var rendered_count: usize = 0;
|
||||
var rendered_opaque_count: usize = 0;
|
||||
|
||||
// Prepare indirect draw commands
|
||||
{
|
||||
@ -830,7 +844,7 @@ pub fn finish(self: *Render) void {
|
||||
var material_map = std.StringHashMap(i32).init(self.frame_arena);
|
||||
|
||||
var materials_count: usize = 0;
|
||||
cmds: for (self.command_buffer[0..self.command_count]) |*cmd| {
|
||||
for (self.command_buffer[0..self.command_count]) |*cmd| {
|
||||
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
||||
// const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max);
|
||||
|
||||
@ -842,10 +856,9 @@ pub fn finish(self: *Render) void {
|
||||
|
||||
// Opaque objects are drawn, start rendering alpha blended objects
|
||||
if (material.blend_mode == .AlphaBlend and !switched_to_alpha_blend) {
|
||||
break :cmds;
|
||||
// switched_to_alpha_blend = true;
|
||||
// gl.enable(gl.BLEND);
|
||||
// gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
rendered_opaque_count = rendered_count;
|
||||
std.log.debug("opaque: {}\n", .{rendered_opaque_count});
|
||||
switched_to_alpha_blend = true;
|
||||
}
|
||||
|
||||
const material_bytes = std.mem.asBytes(&material);
|
||||
@ -868,13 +881,17 @@ pub fn finish(self: *Render) void {
|
||||
.instance_count = 1,
|
||||
.first_index = mesh.indices.offset / 4,
|
||||
.base_vertex = mesh.indices.base_vertex,
|
||||
.base_instance = 0,
|
||||
.base_instance = @intCast(rendered_count),
|
||||
};
|
||||
|
||||
rendered_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rendered_opaque_count == 0) {
|
||||
rendered_opaque_count = rendered_count;
|
||||
}
|
||||
|
||||
{
|
||||
const camera_matrix: *CameraMatrices = @alignCast(@ptrCast(self.camera_matrices[self.tripple_buffer_index * self.uboAlignedSizeOf(CameraMatrices) ..].ptr));
|
||||
camera_matrix.* = .{
|
||||
@ -903,13 +920,15 @@ pub fn finish(self: *Render) void {
|
||||
{
|
||||
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.z_prepass).program);
|
||||
gl.bindVertexArray(self.shadow_vao);
|
||||
gl.depthFunc(gl.LESS);
|
||||
|
||||
self.assetman.vertex_heap.vertices.bind(Render.Attrib.Position.value());
|
||||
checkGLError();
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.assetman.vertex_heap.indices.buffer);
|
||||
checkGLError();
|
||||
|
||||
gl.multiDrawElementsIndirect(gl.TRIANGLES, gl.UNSIGNED_INT, null, @intCast(rendered_count), @sizeOf(DrawIndirectCmd));
|
||||
gl.multiDrawElementsIndirect(gl.TRIANGLES, gl.UNSIGNED_INT, null, @intCast(rendered_opaque_count), @sizeOf(DrawIndirectCmd));
|
||||
checkGLError();
|
||||
}
|
||||
|
||||
// Main pass
|
||||
@ -933,11 +952,25 @@ pub fn finish(self: *Render) void {
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.assetman.vertex_heap.indices.buffer);
|
||||
checkGLError();
|
||||
|
||||
gl.multiDrawElementsIndirect(gl.TRIANGLES, gl.UNSIGNED_INT, null, @intCast(rendered_count), 0);
|
||||
gl.multiDrawElementsIndirect(gl.TRIANGLES, gl.UNSIGNED_INT, null, @intCast(rendered_opaque_count), @sizeOf(DrawIndirectCmd));
|
||||
checkGLError();
|
||||
}
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
gl.depthFunc(gl.LESS);
|
||||
// Alpha Pass
|
||||
const blended_draws_count = rendered_count - rendered_opaque_count;
|
||||
if (blended_draws_count > 0) {
|
||||
std.log.debug("blended: {}\n", .{blended_draws_count});
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
gl.depthFunc(gl.LEQUAL);
|
||||
gl.depthMask(gl.FALSE);
|
||||
|
||||
gl.multiDrawElementsIndirect(gl.TRIANGLES, gl.UNSIGNED_INT, @ptrFromInt(@sizeOf(DrawIndirectCmd) * rendered_opaque_count), @intCast(blended_draws_count), @sizeOf(DrawIndirectCmd));
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
gl.depthFunc(gl.LEQUAL);
|
||||
gl.depthMask(gl.TRUE);
|
||||
}
|
||||
|
||||
// Debug stuff
|
||||
{
|
||||
|
@ -370,6 +370,7 @@ pub const Material = extern struct {
|
||||
pub const BlendMode = enum(u8) {
|
||||
Opaque = 0,
|
||||
AlphaBlend = 1,
|
||||
AlphaMask = 2,
|
||||
};
|
||||
|
||||
albedo: Vec4 = Vec4.one(),
|
||||
|
@ -505,7 +505,7 @@ export fn game_update() bool {
|
||||
gmem.render.drawLight(.{
|
||||
.directional = .{
|
||||
.dir = dir4.toVec3(),
|
||||
.color = color,
|
||||
.color = color.add(Vec3.new(100, 0, 0)),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -193,6 +193,18 @@ fn processScene(allocator: std.mem.Allocator, input: []const u8, output_dir: std
|
||||
}
|
||||
}
|
||||
|
||||
for (texture_outputs) |*tex_out| {
|
||||
defer tex_out.asset.file.close();
|
||||
|
||||
try processTexture(
|
||||
allocator,
|
||||
tex_out.tex_type,
|
||||
@as([*]u8, @ptrCast(tex_out.texture.pcData))[0..@intCast(tex_out.texture.mWidth)],
|
||||
tex_out.asset.file,
|
||||
&tex_out.has_alpha,
|
||||
);
|
||||
}
|
||||
|
||||
// Materials
|
||||
var material_outputs = try allocator.alloc(formats.Material, @intCast(scene.mNumMaterials));
|
||||
if (scene.mMaterials != null) {
|
||||
@ -205,31 +217,41 @@ fn processScene(allocator: std.mem.Allocator, input: []const u8, output_dir: std
|
||||
if (c.aiGetMaterialColor(material, AI_MATKEY_BASE_COLOR, 0, 0, &base_color) == c.aiReturn_SUCCESS) {
|
||||
// TODO: rgba
|
||||
mat_output.albedo = Vec4.new(base_color.r, base_color.g, base_color.b, base_color.a);
|
||||
|
||||
if (std.math.approxEqAbs(f32, base_color.a, 0.0, std.math.floatEps(f32))) {
|
||||
mat_output.blend_mode = .AlphaMask;
|
||||
} else if (base_color.a < 1.0) {
|
||||
mat_output.blend_mode = .AlphaBlend;
|
||||
}
|
||||
}
|
||||
|
||||
if (c.aiGetMaterialTextureCount(material, c.aiTextureType_BASE_COLOR) > 0) {
|
||||
const mat_texture = try getMaterialTexture(allocator, input_dir, material, c.aiTextureType_BASE_COLOR, 0);
|
||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs);
|
||||
var has_alpha = false;
|
||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs, &has_alpha);
|
||||
mat_output.albedo_map.id = entry.getAssetId();
|
||||
if (has_alpha) {
|
||||
mat_output.blend_mode = .AlphaBlend;
|
||||
}
|
||||
}
|
||||
|
||||
_ = c.aiGetMaterialFloat(material, AI_MATKEY_METALLIC_FACTOR, 0, 0, &mat_output.metallic);
|
||||
if (c.aiGetMaterialTextureCount(material, c.aiTextureType_METALNESS) > 0) {
|
||||
const mat_texture = try getMaterialTexture(allocator, input_dir, material, c.aiTextureType_METALNESS, 0);
|
||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs);
|
||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs, null);
|
||||
mat_output.metallic_map.id = entry.getAssetId();
|
||||
}
|
||||
|
||||
_ = c.aiGetMaterialFloat(material, AI_MATKEY_ROUGHNESS_FACTOR, 0, 0, &mat_output.roughness);
|
||||
if (c.aiGetMaterialTextureCount(material, c.aiTextureType_DIFFUSE_ROUGHNESS) > 0) {
|
||||
const mat_texture = try getMaterialTexture(allocator, input_dir, material, c.aiTextureType_DIFFUSE_ROUGHNESS, 0);
|
||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs);
|
||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs, null);
|
||||
mat_output.roughness_map.id = entry.getAssetId();
|
||||
}
|
||||
|
||||
if (c.aiGetMaterialTextureCount(material, c.aiTextureType_NORMALS) > 0) {
|
||||
const mat_texture = try getMaterialTexture(allocator, input_dir, material, c.aiTextureType_NORMALS, 0);
|
||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs);
|
||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs, null);
|
||||
switch (mat_texture.path) {
|
||||
.embedded => |idx| {
|
||||
texture_outputs[idx].tex_type = .Normal;
|
||||
@ -242,12 +264,6 @@ fn processScene(allocator: std.mem.Allocator, input: []const u8, output_dir: std
|
||||
}
|
||||
}
|
||||
|
||||
for (texture_outputs) |tex_out| {
|
||||
defer tex_out.asset.file.close();
|
||||
|
||||
try processTexture(allocator, tex_out.tex_type, @as([*]u8, @ptrCast(tex_out.texture.pcData))[0..@intCast(tex_out.texture.mWidth)], tex_out.asset.file);
|
||||
}
|
||||
|
||||
const meshes: []*c.aiMesh = @ptrCast(scene.mMeshes[0..@intCast(scene.mNumMeshes)]);
|
||||
var mesh_outputs = try allocator.alloc(AssetListEntry, meshes.len);
|
||||
for (meshes, 0..) |mesh, i| {
|
||||
@ -351,6 +367,7 @@ const TextureOutput = struct {
|
||||
texture: *c.aiTexture,
|
||||
asset: AssetOutput,
|
||||
tex_type: TextureType = .Color,
|
||||
has_alpha: bool = false,
|
||||
};
|
||||
|
||||
const AssimpTextureRef = union(enum) {
|
||||
@ -373,13 +390,17 @@ const AssimpTextureRef = union(enum) {
|
||||
return .{ .external = cwd_relative_path };
|
||||
}
|
||||
|
||||
pub fn resolveAssetListEntry(self: AssimpTextureRef, embedded: []const TextureOutput) AssetListEntry {
|
||||
pub fn resolveAssetListEntry(self: AssimpTextureRef, embedded: []const TextureOutput, out_has_alpha: ?*bool) AssetListEntry {
|
||||
switch (self) {
|
||||
.embedded => |idx| {
|
||||
if (out_has_alpha) |has_alpha| {
|
||||
has_alpha.* = embedded[idx].has_alpha;
|
||||
}
|
||||
return embedded[idx].asset.list_entry;
|
||||
},
|
||||
.external => |path| {
|
||||
// TODO: resolve relative to current input file
|
||||
// TODO: has_alpha
|
||||
return AssetListEntry{ .src_path = AssetPath.fromString(path), .type = .Texture };
|
||||
},
|
||||
}
|
||||
@ -547,7 +568,8 @@ fn processTextureFromFile(allocator: std.mem.Allocator, input: []const u8, outpu
|
||||
const contents = try std.fs.cwd().readFileAlloc(allocator, input, ASSET_MAX_BYTES);
|
||||
const texture_type = guessTextureTypeFromName(input);
|
||||
|
||||
try processTexture(allocator, texture_type, contents, output.file);
|
||||
var has_alpha = false;
|
||||
try processTexture(allocator, texture_type, contents, output.file, &has_alpha);
|
||||
}
|
||||
|
||||
/// Using naming conventions
|
||||
@ -576,7 +598,7 @@ const TextureType = enum {
|
||||
HDR,
|
||||
};
|
||||
|
||||
fn processTexture(allocator: std.mem.Allocator, texture_type: TextureType, contents: []const u8, out_file: std.fs.File) !void {
|
||||
fn processTexture(allocator: std.mem.Allocator, texture_type: TextureType, contents: []const u8, out_file: std.fs.File, out_has_alpha: *bool) !void {
|
||||
var width_int: c_int = 0;
|
||||
var height_int: c_int = 0;
|
||||
var comps: c_int = 0;
|
||||
@ -601,6 +623,16 @@ fn processTexture(allocator: std.mem.Allocator, texture_type: TextureType, conte
|
||||
|
||||
const rgba_data = rgba_data_c[0 .. width * height * 4];
|
||||
|
||||
if (comps == 4) {
|
||||
var i: usize = 3;
|
||||
while (i < rgba_data.len) : (i += 4) {
|
||||
if (rgba_data[i] < 255) {
|
||||
out_has_alpha.* = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var padded_width: usize = width;
|
||||
var padded_height: usize = height;
|
||||
var rgba_data_padded = rgba_data;
|
||||
|
Loading…
x
Reference in New Issue
Block a user