add basic edge shading

This commit is contained in:
catangent 2024-12-23 18:45:07 +00:00
parent c600c82e8f
commit c19a19166b
5 changed files with 73 additions and 182 deletions

View file

@ -6,6 +6,13 @@ uniform vec2 textureTiling;
in vec2 fragTexCoord;
in vec2 fragTexCoord2;
in vec4 fragColor;
flat in int ambientOcclusionSide1;
flat in int ambientOcclusionSide2;
flat in int ambientOcclusionCorner1;
flat in int ambientOcclusionCorner2;
flat in int ambientOcclusionCorner3;
flat in int quadHeight;
flat in int quadWidth;
out vec4 outColor;
@ -13,4 +20,10 @@ void main()
{
vec2 texCoord = (floor(fragTexCoord*textureTiling) + fract(fragTexCoord2)) / textureTiling;
outColor = texture(diffuseMap, texCoord);
ivec2 floorFragTexCoord2 = ivec2(fragTexCoord2);
if ((fragTexCoord2.x < 0.05 || fragTexCoord2.x > quadWidth-0.05) && (((ambientOcclusionSide1 >> floorFragTexCoord2.y) & 1) == 1)) outColor *= 0.5;
else if((fragTexCoord2.y < 0.05 || fragTexCoord2.y > quadHeight-0.05) && (((ambientOcclusionSide2 >> floorFragTexCoord2.y) & 1) == 1)) outColor *= 0.5;
outColor.a = 1;
}

View file

@ -2,13 +2,22 @@
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec2 vertexTexCoord2;
in vec2 vertexTexCoord2;
in vec4 vertexColor;
in vec4 vertexTangent; // metadata1
out vec2 fragTexCoord;
out vec2 fragTexCoord2;
out vec4 fragColor;
flat out int ambientOcclusionSide1;
flat out int ambientOcclusionSide2;
flat out int ambientOcclusionCorner1;
flat out int ambientOcclusionCorner2;
flat out int ambientOcclusionCorner3;
flat out int quadHeight;
flat out int quadWidth;
uniform mat4 mvp;
void main() {
@ -16,4 +25,15 @@ void main() {
fragColor = vertexColor;
fragTexCoord2 = vertexTexCoord2;
gl_Position = mvp*vec4(vertexPosition, 1.0);
// metadata 1 processing
ambientOcclusionSide1 = floatBitsToInt(vertexTangent.x);
ambientOcclusionSide2 = floatBitsToInt(vertexTangent.y);
int metadata1Z = floatBitsToInt(vertexTangent.z);
int metadata1W = floatBitsToInt(vertexTangent.w);
ambientOcclusionCorner1 = (metadata1Z & 0x1) >> 0;
ambientOcclusionCorner2 = (metadata1Z & 0x2) >> 1;
ambientOcclusionCorner3 = (metadata1Z & 0x4) >> 2;
quadHeight = (metadata1Z & 0x1f8) >> 3;
quadWidth = (metadata1Z & 0x7e00) >> 9;
}

View file

@ -1,177 +0,0 @@
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);
}

View file

@ -3,6 +3,7 @@ const raylib_helper = @import("../lib_helpers/raylib_helper.zig");
const raylib = raylib_helper.raylib;
const v3 = raylib_helper.v3;
const A7r = std.mem.Allocator;
const comptimePrint = std.fmt.comptimePrint;
const RawQuad = struct {
tile: u32,
@ -15,6 +16,24 @@ const RawQuad = struct {
height: f32,
};
const Metadata1 = packed struct {
ambient_occlusion_1: u32,
ambient_occlusion_2: u32,
ambient_occlusion_corner1: bool,
ambient_occlusion_corner2: bool,
ambient_occlusion_corner3: bool,
quad_height: u6,
quad_width: u6,
unused: u17 = 0,
unused_2: u32 = 0,
};
comptime {
if (@bitSizeOf(Metadata1) != 128) {
@compileError(comptimePrint("Metadata 1 has wrong size. Expected 128 bits, found {}", .{@bitSizeOf(Metadata1)}));
}
}
pub const Chunk = struct {
tiles: []u32,
a7r: A7r,
@ -151,6 +170,7 @@ pub const Chunk = struct {
const texcoords: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2)));
const texcoords2: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2)));
const normals: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 3)));
const metadata1_packed: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 4)));
for (raw_quads.items, 0..) |raw_quad, i| {
if (raw_quad.tile <= 0) continue;
@ -214,6 +234,22 @@ pub const Chunk = struct {
texcoords[12 * i + 11] = bottom_uv;
texcoords2[12 * i + 10] = 0.0;
texcoords2[12 * i + 11] = raw_quad.height;
for (0..6) |j| {
const metadata1 = Metadata1{
.ambient_occlusion_1 = 0xffffffff,
.ambient_occlusion_2 = 0xffffffff,
.ambient_occlusion_corner1 = true,
.ambient_occlusion_corner2 = true,
.ambient_occlusion_corner3 = true,
.quad_height = @intFromFloat(raw_quad.height),
.quad_width = @intFromFloat(raw_quad.width),
};
const metadata1_baked: [4]f32 = @bitCast(metadata1);
for (0..4) |k| {
metadata1_packed[24 * i + 4 * j + k] = @bitCast(@as(f32, metadata1_baked[k]));
}
}
}
var mesh = raylib.Mesh{
@ -224,6 +260,7 @@ pub const Chunk = struct {
.texcoords = texcoords,
.texcoords2 = texcoords2,
.normals = normals,
.tangents = metadata1_packed,
.vaoId = 0,
.vboId = null,

View file

@ -2,11 +2,9 @@
yoink implementation of mesh into meshes.zig so i could modify it to add ambient occlusion vars
implement ambient occlusion either
- via passing extra info to shader (can use 132 bits to indicate what tiles around the quad are obsuring light. need to pass as an extra variable)
implement animated textures by either
- making literally everything animated
- somehow passing extra info to shader
implement animations (smooth or minecraft like), random orientation/mirroring, metallicity (shine on edges)
implement second layer of textures on top of first one for more details
limit vertical camera rotations
update libraries like raylib
# future tasks
implement chunk meshing cache to reduce delay on block placement