const std = @import("std"); const raylib_helper = @import("../lib_helpers/raylib_helper.zig"); const raylib = raylib_helper.raylib; const MAX_VBOS = 4; const VERTICES_VBO_ID = 0; const TEXCOORDS_VBO_ID = 1; const TEXCOORDS2_VBO_ID = 2; const NORMALS_VBO_ID = 3; const ChunkMesh = packed struct { vertexCount: i32, triangleCount: i32, vertices: [*]f32, // vertex position, XYZ, 3 vars per vertex texcoords: [*]f32, // vertex texture coorinates, UV, 2 vars per vertex texcoords2: [*]f32, // vertex second texture coorinates, UV, 2 vars per vertex normals: [*]f32, // vertex normals, XYZ, 3 vars per vertex vaoId: u32, vboId: [*]u32, }; pub fn UploadChunkMesh(mesh: ChunkMesh, dynamic: bool) void { if (mesh.vaoId > 0) { raylib.TraceLog(raylib.LOG_WARNING, "VAO: [ID %i] Trying to re-load an already loaded chunk mesh", mesh.vaoId); return; } mesh.vboId = @ptrCast(@alignCast(raylib.MemAlloc(@sizeOf(u32) * MAX_VBOS))); mesh.vaoId = 0; mesh.vboId[VERTICES_VBO_ID] = 0; mesh.vboId[TEXCOORDS_VBO_ID] = 0; mesh.vboId[TEXCOORDS2_VBO_ID] = 0; mesh.vboId[NORMALS_VBO_ID] = 0; mesh.vaoId = raylib.rlLoadVertexArray(); raylib.rlEnableVertexArray(mesh.vaoId); mesh.vboId[VERTICES_VBO_ID] = raylib.rlLoadVertexBuffer(mesh.vertices, mesh.vertexCount * 3 * @sizeOf(f32), dynamic); raylib.rlSetVertexAttribute(VERTICES_VBO_ID, 3, raylib.RL_FLOAT, false, 0, 0); raylib.rlEnableVertexAttribute(VERTICES_VBO_ID); mesh.vboId[TEXCOORDS_VBO_ID] = raylib.rlLoadVertexBuffer(mesh.texcoords, mesh.vertexCount * 2 * @sizeOf(f32), dynamic); raylib.rlSetVertexAttribute(TEXCOORDS_VBO_ID, 2, raylib.RL_FLOAT, false, 0, 0); raylib.rlEnableVertexAttribute(TEXCOORDS_VBO_ID); mesh.vboId[TEXCOORDS2_VBO_ID] = raylib.rlLoadVertexBuffer(mesh.texcoords, mesh.vertexCount * 2 * @sizeOf(f32), dynamic); raylib.rlSetVertexAttribute(TEXCOORDS2_VBO_ID, 2, raylib.RL_FLOAT, false, 0, 0); raylib.rlEnableVertexAttribute(TEXCOORDS2_VBO_ID); mesh.vboId[NORMALS_VBO_ID] = raylib.rlLoadVertexBuffer(mesh.vertices, mesh.vertexCount * 3 * @sizeOf(f32), dynamic); raylib.rlSetVertexAttribute(NORMALS_VBO_ID, 3, raylib.RL_FLOAT, false, 0, 0); raylib.rlEnableVertexAttribute(NORMALS_VBO_ID); if (mesh.vaoId > 0) { raylib.TraceLog(raylib.LOG_INFO, "VAO: [ID %i] Chunk mesh uploaded successfully to VRAM (GPU)", mesh.vaoId); } else { raylib.TraceLog(raylib.LOG_INFO, "VBO: Chunk mesh uploaded successfully to VRAM (GPU)"); } raylib.rlDisableVertexArray(); } pub fn UpdateChunkMeshBuffer(mesh: ChunkMesh, index: i32, data: ?*const anyopaque, dataSize: i32, offset: i32) void { raylib.rlUpdateVertexBuffer(mesh.vboId[index], data, dataSize, offset); } pub fn UnloadChunkMesh(mesh: ChunkMesh) void { raylib.rlUnloadVertexArray(mesh.vaoId); if (mesh.vboId != null) { for (0..MAX_VBOS) |i| { raylib.rlUnloadVertexBuffer(mesh.vboId[i]); } } raylib.MemFree(mesh.vboId); raylib.MemFree(mesh.vertices); raylib.MemFree(mesh.texcoords); raylib.MemFree(mesh.texcoords2); raylib.MemFree(mesh.normals); } pub fn DrawChunkMesh(mesh: ChunkMesh, material: raylib.Material, transform: raylib.Matrix) void { raylib.rlEnableShader(material.shader.id); if (material.shader.locs[raylib.SHADER_LOC_COLOR_DIFFUSE] != -1) { const values: [4]f32 = [4]f32{ @as(u32, @floatFromInt(material.maps[raylib.MATERIAL_MAP_DIFFUSE].color.r)) / 255.0, @as(u32, @floatFromInt(material.maps[raylib.MATERIAL_MAP_DIFFUSE].color.g)) / 255.0, @as(u32, @floatFromInt(material.maps[raylib.MATERIAL_MAP_DIFFUSE].color.b)) / 255.0, @as(u32, @floatFromInt(material.maps[raylib.MATERIAL_MAP_DIFFUSE].color.a)) / 255.0, }; raylib.rlSetUniform(material.shader.locs[raylib.SHADER_LOC_COLOR_DIFFUSE], values, raylib.SHADER_UNIFORM_VEC4, 1); } if (material.shader.locs[raylib.SHADER_LOC_COLOR_SPECULAR] != -1) { const values: [4]f32 = [4]f32{ @as(u32, @floatFromInt(material.maps[raylib.MATERIAL_MAP_SPECULAR].color.r)) / 255.0, @as(u32, @floatFromInt(material.maps[raylib.MATERIAL_MAP_SPECULAR].color.g)) / 255.0, @as(u32, @floatFromInt(material.maps[raylib.MATERIAL_MAP_SPECULAR].color.b)) / 255.0, @as(u32, @floatFromInt(material.maps[raylib.MATERIAL_MAP_SPECULAR].color.a)) / 255.0, }; raylib.rlSetUniform(material.shader.locs[raylib.SHADER_LOC_COLOR_SPECULAR], values, raylib.SHADER_UNIFORM_VEC4, 1); } var matModel: raylib.Matrix = raylib.MatrixIdentity(); const matView: raylib.Matrix = raylib.rlGetMatrixModelview(); var matModelView: raylib.Matrix = raylib.MatrixIdentity(); const matProjection: raylib.Matrix = raylib.rlGetMatrixProjection(); if (material.shader.locs[raylib.SHADER_LOC_MATRIX_VIEW] != -1) raylib.rlSetUniformMatrix(material.shader.locs[raylib.SHADER_LOC_MATRIX_VIEW], matView); if (material.shader.locs[raylib.SHADER_LOC_MATRIX_PROJECTION] != -1) raylib.rlSetUniformMatrix(material.shader.locs[raylib.SHADER_LOC_MATRIX_PROJECTION], matProjection); matModel = raylib.MatrixMultiply(transform, raylib.rlGetMatrixTransform()); if (material.shader.locs[raylib.SHADER_LOC_MATRIX_MODEL] != -1) raylib.rlSetUniformMatrix(material.shader.locs[raylib.SHADER_LOC_MATRIX_MODEL], matModel); matModelView = raylib.MatrixMultiply(matModel, matView); if (material.shader.locs[raylib.SHADER_LOC_MATRIX_NORMAL] != -1) raylib.rlSetUniformMatrix(material.shader.locs[raylib.SHADER_LOC_MATRIX_NORMAL], raylib.MatrixTranspose(raylib.MatrixInvert(matModel))); for (0..raylib.MAX_MATERIAL_MAPS) |i| { if (material.maps[i].texture.id > 0) { raylib.rlActiveTextureSlot(i); if (i == raylib.MATERIAL_MAP_IRRADIANCE or i == raylib.MATERIAL_MAP_PREFILTER or i == raylib.MATERIAL_MAP_CUBEMAP) { raylib.rlEnableTextureCubemap(material.maps[i].texture.id); } else { raylib.rlEnableTexture(material.maps[i].texture.id); } raylib.rlSetUniform(material.shader.locs[raylib.SHADER_LOC_MAP_DIFFUSE + i], &i, raylib.SHADER_UNIFORM_INT, 1); } } if (!raylib.rlEnableVertexArray(mesh.vaoId)) { raylib.rlEnableVertexBuffer(mesh.vboId[0]); raylib.rlSetVertexAttribute(material.shader.locs[VERTICES_VBO_ID], 3, raylib.RL_FLOAT, 0, 0, 0); raylib.rlEnableVertexAttribute(material.shader.locs[VERTICES_VBO_ID]); raylib.rlEnableVertexBuffer(mesh.vboId[1]); raylib.rlSetVertexAttribute(material.shader.locs[TEXCOORDS_VBO_ID], 2, raylib.RL_FLOAT, 0, 0, 0); raylib.rlEnableVertexAttribute(material.shader.locs[TEXCOORDS_VBO_ID]); raylib.rlEnableVertexBuffer(mesh.vboId[2]); raylib.rlSetVertexAttribute(material.shader.locs[TEXCOORDS2_VBO_ID], 2, raylib.RL_FLOAT, 0, 0, 0); raylib.rlEnableVertexAttribute(material.shader.locs[TEXCOORDS2_VBO_ID]); raylib.rlEnableVertexBuffer(mesh.vboId[3]); raylib.rlSetVertexAttribute(material.shader.locs[NORMALS_VBO_ID], 3, raylib.RL_FLOAT, 0, 0, 0); raylib.rlEnableVertexAttribute(material.shader.locs[NORMALS_VBO_ID]); } var eyeCount = 1; if (raylib.rlIsStereoRenderEnabled()) { eyeCount = 2; } for (0..eyeCount) |eye| { var matModelViewProjection: raylib.Matrix = raylib.MatrixIdentity(); if (eyeCount == 1) { matModelViewProjection = raylib.MatrixMultiply(matModelView, matProjection); } else { raylib.rlViewport(@divTrunc(eye * raylib.rlGetFramebufferWidth(), 2), 0, @divTrunc(raylib.rlGetFramebufferWidth(), 2), raylib.rlGetFramebufferHeight()); matModelViewProjection = raylib.MatrixMultiply(raylib.MatrixMultiply(matModelView, raylib.rlGetMatrixViewOffsetStereo(eye)), raylib.rlGetMatrixProjectionStereo(eye)); } raylib.rlSetUniformMatrix(material.shader.locs[raylib.SHADER_LOC_MATRIX_MVP], matModelViewProjection); raylib.rlDrawVertexArray(0, mesh.vertexCount); } for (0..raylib.MAX_MATERIAL_MAPS) |i| { if (material.maps[i].texture.id > 0) { raylib.rlActiveTextureSlot(i); if (((i == raylib.MATERIAL_MAP_IRRADIANCE) or (i == raylib.MATERIAL_MAP_PREFILTER)) or (i == raylib.MATERIAL_MAP_CUBEMAP)) { raylib.rlDisableTextureCubemap(); } else { raylib.rlDisableTexture(); } } } raylib.rlDisableVertexArray(); raylib.rlDisableVertexBuffer(); raylib.rlDisableVertexBufferElement(); raylib.rlDisableShader(); raylib.rlSetMatrixModelview(matView); raylib.rlSetMatrixProjection(matProjection); }