Add tangents

This commit is contained in:
sergeypdev 2024-02-19 04:12:19 +04:00
parent e764879f17
commit 6e75910bef
5 changed files with 52 additions and 12 deletions

View File

@ -30,6 +30,7 @@ VERTEX_EXPORT VertexData {
vec3 position; vec3 position;
vec3 normal; vec3 normal;
vec2 uv; vec2 uv;
vec3 tangent;
} VertexOut; } VertexOut;
#if VERTEX_SHADER #if VERTEX_SHADER
@ -37,6 +38,7 @@ VERTEX_EXPORT VertexData {
layout(location = 0) in vec3 aPos; layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNorm; layout(location = 1) in vec3 aNorm;
layout(location = 2) in vec2 aUV; layout(location = 2) in vec2 aUV;
layout(location = 3) in vec3 aTangent;
void main() { void main() {
gl_Position = projection * view * model * vec4(aPos.xyz, 1.0); gl_Position = projection * view * model * vec4(aPos.xyz, 1.0);
@ -44,6 +46,7 @@ void main() {
VertexOut.position = posWorld.xyz / posWorld.w; VertexOut.position = posWorld.xyz / posWorld.w;
VertexOut.normal = aNorm; VertexOut.normal = aNorm;
VertexOut.uv = aUV; VertexOut.uv = aUV;
VertexOut.tangent = aTangent;
} }
#endif // VERTEX_SHADER #endif // VERTEX_SHADER

View File

@ -235,6 +235,11 @@ const NullMesh = LoadedMesh{
.offset = 0, .offset = 0,
.stride = 0, .stride = 0,
}, },
.tangents = BufferSlice{
.buffer = 0,
.offset = 0,
.stride = 0,
},
.uvs = BufferSlice{ .uvs = BufferSlice{
.buffer = 0, .buffer = 0,
.offset = 0, .offset = 0,
@ -265,7 +270,7 @@ fn loadMeshErr(self: *AssetManager, id: AssetId) !*const LoadedMesh {
const data = try self.loadFile(self.frame_arena, path, MESH_MAX_BYTES); const data = try self.loadFile(self.frame_arena, path, MESH_MAX_BYTES);
const mesh = formats.Mesh.fromBuffer(data.bytes); const mesh = formats.Mesh.fromBuffer(data.bytes);
var bufs = [_]gl.GLuint{ 0, 0, 0, 0 }; var bufs = [_]gl.GLuint{ 0, 0, 0, 0, 0 };
gl.createBuffers(bufs.len, &bufs); gl.createBuffers(bufs.len, &bufs);
errdefer gl.deleteBuffers(bufs.len, &bufs); errdefer gl.deleteBuffers(bufs.len, &bufs);
@ -273,38 +278,44 @@ fn loadMeshErr(self: *AssetManager, id: AssetId) !*const LoadedMesh {
std.debug.assert(vertices != 0); std.debug.assert(vertices != 0);
const normals = bufs[1]; const normals = bufs[1];
std.debug.assert(normals != 0); std.debug.assert(normals != 0);
const uvs = bufs[2]; const tangents = bufs[2];
std.debug.assert(tangents != 0);
const uvs = bufs[3];
std.debug.assert(uvs != 0); std.debug.assert(uvs != 0);
const indices = bufs[3]; const indices = bufs[4];
std.debug.assert(indices != 0); std.debug.assert(indices != 0);
gl.namedBufferStorage( gl.namedBufferStorage(
vertices, vertices,
@intCast(mesh.vertices.len * @sizeOf(formats.Vector3)), @intCast(mesh.vertices.len * @sizeOf(formats.Vector3)),
@ptrCast(mesh.vertices), @ptrCast(mesh.vertices.ptr),
0, 0,
); );
gl.namedBufferStorage( gl.namedBufferStorage(
normals, normals,
@intCast(mesh.normals.len * @sizeOf(formats.Vector3)), @intCast(mesh.normals.len * @sizeOf(formats.Vector3)),
@ptrCast(mesh.normals), @ptrCast(mesh.normals.ptr),
0,
);
gl.namedBufferStorage(
tangents,
@intCast(mesh.tangents.len * @sizeOf(formats.Vector3)),
@ptrCast(mesh.tangents.ptr),
0, 0,
); );
gl.namedBufferStorage( gl.namedBufferStorage(
uvs, uvs,
@intCast(mesh.uvs.len * @sizeOf(formats.Vector2)), @intCast(mesh.uvs.len * @sizeOf(formats.Vector2)),
@ptrCast(mesh.uvs), @ptrCast(mesh.uvs.ptr),
0, 0,
); );
gl.namedBufferStorage( gl.namedBufferStorage(
indices, indices,
@intCast(mesh.indices.len * @sizeOf(formats.Index)), @intCast(mesh.indices.len * @sizeOf(formats.Index)),
@ptrCast(mesh.indices), @ptrCast(mesh.indices.ptr),
0, 0,
); );
// gl.bindVertexBuffer(_bindingindex: GLuint, _buffer: GLuint, _offset: GLintptr, _stride: GLsizei)
const loaded_mesh = LoadedMesh{ const loaded_mesh = LoadedMesh{
.aabb = .{ .aabb = .{
.min = Vec3.new(mesh.aabb.min.x, mesh.aabb.min.y, mesh.aabb.min.z), .min = Vec3.new(mesh.aabb.min.x, mesh.aabb.min.y, mesh.aabb.min.z),
@ -320,6 +331,11 @@ fn loadMeshErr(self: *AssetManager, id: AssetId) !*const LoadedMesh {
.offset = 0, .offset = 0,
.stride = @sizeOf(formats.Vector3), .stride = @sizeOf(formats.Vector3),
}, },
.tangents = .{
.buffer = tangents,
.offset = 0,
.stride = @sizeOf(formats.Vector3),
},
.uvs = .{ .uvs = .{
.buffer = uvs, .buffer = uvs,
.offset = 0, .offset = 0,
@ -422,6 +438,7 @@ const LoadedMesh = struct {
aabb: AABB, aabb: AABB,
positions: BufferSlice, positions: BufferSlice,
normals: BufferSlice, normals: BufferSlice,
tangents: BufferSlice,
uvs: BufferSlice, uvs: BufferSlice,
indices: IndexSlice, indices: IndexSlice,
}; };
@ -572,7 +589,7 @@ fn unloadAssetWithDependees(self: *AssetManager, id: AssetId) void {
switch (asset.*) { switch (asset.*) {
.mesh => |*mesh| { .mesh => |*mesh| {
gl.deleteBuffers(4, &[_]gl.GLuint{ mesh.positions.buffer, mesh.normals.buffer, mesh.uvs.buffer, mesh.indices.buffer }); gl.deleteBuffers(5, &[_]gl.GLuint{ mesh.positions.buffer, mesh.normals.buffer, mesh.tangents.buffer, mesh.uvs.buffer, mesh.indices.buffer });
}, },
.shader => |*shader| { .shader => |*shader| {
self.allocator.free(shader.source); self.allocator.free(shader.source);

View File

@ -51,13 +51,16 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
gl.vertexArrayAttribFormat(vao, Attrib.Position.value(), 3, gl.FLOAT, gl.FALSE, 0); gl.vertexArrayAttribFormat(vao, Attrib.Position.value(), 3, gl.FLOAT, gl.FALSE, 0);
// normals // normals
// gl.vertexArrayVertexBuffer(vao, 1, normals, 0, @sizeOf(formats.Vector3));
gl.enableVertexArrayAttrib(vao, Attrib.Normal.value()); gl.enableVertexArrayAttrib(vao, Attrib.Normal.value());
gl.vertexArrayAttribBinding(vao, Attrib.Normal.value(), 1); gl.vertexArrayAttribBinding(vao, Attrib.Normal.value(), 1);
gl.vertexArrayAttribFormat(vao, Attrib.Normal.value(), 3, gl.FLOAT, gl.FALSE, 0); gl.vertexArrayAttribFormat(vao, Attrib.Normal.value(), 3, gl.FLOAT, gl.FALSE, 0);
// tangents
gl.enableVertexArrayAttrib(vao, Attrib.Tangent.value());
gl.vertexArrayAttribBinding(vao, Attrib.Tangent.value(), 3);
gl.vertexArrayAttribFormat(vao, Attrib.Tangent.value(), 3, gl.FLOAT, gl.FALSE, 0);
// uvs // uvs
// gl.vertexArrayVertexBuffer(vao, 1, normals, 0, @sizeOf(formats.Vector3));
gl.enableVertexArrayAttrib(vao, Attrib.UV.value()); gl.enableVertexArrayAttrib(vao, Attrib.UV.value());
gl.vertexArrayAttribBinding(vao, Attrib.UV.value(), 2); gl.vertexArrayAttribBinding(vao, Attrib.UV.value(), 2);
gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0); gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0);
@ -185,6 +188,7 @@ pub fn draw(self: *Render, cmd: DrawCommand) void {
const mesh = self.assetman.resolveMesh(cmd.mesh); const mesh = self.assetman.resolveMesh(cmd.mesh);
mesh.positions.bind(Render.Attrib.Position.value()); mesh.positions.bind(Render.Attrib.Position.value());
mesh.normals.bind(Render.Attrib.Normal.value()); mesh.normals.bind(Render.Attrib.Normal.value());
mesh.tangents.bind(Render.Attrib.Tangent.value());
mesh.uvs.bind(Render.Attrib.UV.value()); mesh.uvs.bind(Render.Attrib.UV.value());
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indices.buffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indices.buffer);
gl.drawElements( gl.drawElements(
@ -237,6 +241,7 @@ pub const Attrib = enum(gl.GLuint) {
Position = 0, Position = 0,
Normal = 1, Normal = 1,
UV = 2, UV = 2,
Tangent = 3,
pub inline fn value(self: Attrib) gl.GLuint { pub inline fn value(self: Attrib) gl.GLuint {
return @intFromEnum(self); return @intFromEnum(self);

View File

@ -24,6 +24,7 @@ pub const Mesh = struct {
vertices: []align(1) Vector3, vertices: []align(1) Vector3,
normals: []align(1) Vector3, normals: []align(1) Vector3,
tangents: []align(1) Vector3,
uvs: []align(1) Vector2, uvs: []align(1) Vector2,
indices: []align(1) Index, indices: []align(1) Index,
@ -54,6 +55,8 @@ pub const Mesh = struct {
offset += size; offset += size;
const normals = std.mem.bytesAsSlice(Vector3, buffer[offset .. offset + size]); const normals = std.mem.bytesAsSlice(Vector3, buffer[offset .. offset + size]);
offset += size; offset += size;
const tangents = std.mem.bytesAsSlice(Vector3, buffer[offset .. offset + size]);
offset += size;
size = vert_len * @sizeOf(Vector2); size = vert_len * @sizeOf(Vector2);
const uvs = std.mem.bytesAsSlice(Vector2, buffer[offset .. offset + size]); const uvs = std.mem.bytesAsSlice(Vector2, buffer[offset .. offset + size]);
@ -67,6 +70,7 @@ pub const Mesh = struct {
.aabb = aabb, .aabb = aabb,
.vertices = vertices, .vertices = vertices,
.normals = normals, .normals = normals,
.tangents = tangents,
.uvs = uvs, .uvs = uvs,
.indices = indices, .indices = indices,
}; };
@ -92,6 +96,9 @@ pub fn writeMesh(writer: anytype, value: Mesh, endian: std.builtin.Endian) !void
for (value.normals) |n| { for (value.normals) |n| {
try writeVector3(writer, n, endian); try writeVector3(writer, n, endian);
} }
for (value.tangents) |t| {
try writeVector3(writer, t, endian);
}
for (value.uvs) |uv| { for (value.uvs) |uv| {
try writeVector2(writer, uv, endian); try writeVector2(writer, uv, endian);
} }

View File

@ -83,11 +83,13 @@ fn processMesh(allocator: std.mem.Allocator, input: [*:0]const u8, output: []con
const mesh: *c.aiMesh = @ptrCast(scene.mMeshes[0]); const mesh: *c.aiMesh = @ptrCast(scene.mMeshes[0]);
if (mesh.mNormals == null) return error.MissingNormals; if (mesh.mNormals == null) return error.MissingNormals;
if (mesh.mTangents == null) return error.MissingTangents;
if (mesh.mTextureCoords[0] == null) return error.MissingUVs; if (mesh.mTextureCoords[0] == null) return error.MissingUVs;
if (mesh.mNumUVComponents[0] != 2) return error.WrongUVComponents; if (mesh.mNumUVComponents[0] != 2) return error.WrongUVComponents;
var vertices = try allocator.alloc(Vector3, @intCast(mesh.mNumVertices)); var vertices = try allocator.alloc(Vector3, @intCast(mesh.mNumVertices));
var normals = try allocator.alloc(Vector3, @intCast(mesh.mNumVertices)); var normals = try allocator.alloc(Vector3, @intCast(mesh.mNumVertices));
var tangents = try allocator.alloc(Vector3, @intCast(mesh.mNumVertices));
var uvs = try allocator.alloc(Vector2, @intCast(mesh.mNumVertices)); var uvs = try allocator.alloc(Vector2, @intCast(mesh.mNumVertices));
var indices = try allocator.alloc(formats.Index, @intCast(mesh.mNumFaces * 3)); // triangles var indices = try allocator.alloc(formats.Index, @intCast(mesh.mNumFaces * 3)); // triangles
@ -103,6 +105,11 @@ fn processMesh(allocator: std.mem.Allocator, input: [*:0]const u8, output: []con
.y = mesh.mNormals[i].y, .y = mesh.mNormals[i].y,
.z = mesh.mNormals[i].z, .z = mesh.mNormals[i].z,
}; };
tangents[i] = .{
.x = mesh.mTangents[i].x,
.y = mesh.mTangents[i].y,
.z = mesh.mTangents[i].z,
};
uvs[i] = .{ uvs[i] = .{
.x = mesh.mTextureCoords[0][i].x, .x = mesh.mTextureCoords[0][i].x,
.y = mesh.mTextureCoords[0][i].y, .y = mesh.mTextureCoords[0][i].y,
@ -136,6 +143,7 @@ fn processMesh(allocator: std.mem.Allocator, input: [*:0]const u8, output: []con
}, },
.vertices = vertices, .vertices = vertices,
.normals = normals, .normals = normals,
.tangents = tangents,
.uvs = uvs, .uvs = uvs,
.indices = indices, .indices = indices,
}; };