Basic directional shadow map

This commit is contained in:
sergeypdev 2024-03-02 15:41:49 +04:00
parent aec4a4a882
commit 73501f7991
7 changed files with 327 additions and 124 deletions

View File

@ -43,6 +43,9 @@ layout(location = 13) uniform vec3 emission;
layout(location = 14, bindless_sampler) uniform sampler2D emission_map;
layout(location = 15) uniform vec2 emission_map_uv_scale = vec2(1);
layout(location = 16, bindless_sampler) uniform sampler2DArrayShadow shadow_maps;
layout(location = 17) uniform mat4 shadow_map_vp;
// Input, output blocks
@ -50,6 +53,7 @@ VERTEX_EXPORT VertexData {
vec3 vPos;
vec2 uv;
mat3 vTBN;
vec3 wPos;
} VertexOut;
#if VERTEX_SHADER
@ -70,6 +74,8 @@ void main() {
vec3 B = normalize(vec3(view * model * vec4(aBitangent, 0.0)));
vec3 N = normalize(vec3(view * model * vec4(aNormal, 0.0)));
VertexOut.vTBN = mat3(T, B, N);
vec4 wPos = model * vec4(aPos.xyz, 1.0);
VertexOut.wPos = wPos.xyz / wPos.w;
}
#endif // VERTEX_SHADER
@ -177,10 +183,24 @@ void main() {
vec3 finalColor = vec3(0);
for (int i = 0; i < lights_count; i++) {
finalColor += microfacetModel(material, lights[i], VertexOut.vPos, N);
}
float shadow_mult = 1;
// finalColor += microfacetModel(material, Light(vec4(VertexOut.vPos + N, 0.01), vec4(1, 1, 1, 10)), VertexOut.vPos, N);
//// TODO: Shadows for directional light only for now
if (lights[i].vPos.w == 0) {
vec4 shadow_pos = shadow_map_vp * vec4(VertexOut.wPos, 1.0);
shadow_pos /= shadow_pos.w;
shadow_pos.xyz = shadow_pos.xyz * 0.5 + 0.5; // [-1, 1] to [0, 1]
float bias = 0.005;
shadow_pos.z -= bias;
vec4 texcoord;
texcoord.xyw = shadow_pos.xyz; // sampler2DArrayShadow strange texcoord mapping
texcoord.z = 0; // First shadow map
shadow_mult = texture(shadow_maps, texcoord).r;
}
finalColor += microfacetModel(material, lights[i], VertexOut.vPos, N) * shadow_mult;
}
FragColor = vec4(finalColor, 1.0f);

View File

@ -0,0 +1,28 @@
// UBOs
layout(std140, binding = 0) uniform Matrices {
mat4 projection;
mat4 view;
};
// Uniforms
layout(location = 1) uniform mat4 model;
// Input, output blocks
#if VERTEX_SHADER
layout(location = 0) in vec3 aPos;
void main() {
gl_Position = projection * view * model * vec4(aPos.xyz, 1.0);
}
#endif // VERTEX_SHADER
#if FRAGMENT_SHADER
void main() {
gl_FragDepth = gl_FragCoord.z / gl_FragCoord.w;
}
#endif // FRAGMNET_SHADER

View File

@ -0,0 +1,6 @@
{
"shader": "shadow.glsl",
"vertex": true,
"fragment": true
}

View File

@ -15,6 +15,7 @@ const Quat = za.Quat;
pub const MAX_FRAMES_QUEUED = 3;
pub const MAX_POINT_LIGHTS = 8;
pub const MAX_DRAW_COMMANDS = 4096;
pub const Render = @This();
@ -31,7 +32,15 @@ camera_ubo: gl.GLuint = 0,
camera_matrices: []u8 = &.{},
point_lights_ubo: gl.GLuint = 0,
point_lights: []u8 = &.{},
command_buffer: [MAX_DRAW_COMMANDS]DrawCommand = undefined,
command_count: usize = 0,
ubo_align: usize = 0,
shadow_vao: gl.GLuint = 0,
shadow_texture_arrray: gl.GLuint = 0,
shadow_texture_handle: gl.GLuint64 = 0,
shadow_framebuffer: gl.GLuint = 0,
shadow_matrices_buffer: gl.GLuint = 0,
shadow_matrices: CameraMatrices = .{},
pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetman: *AssetManager) Render {
var render = Render{
@ -47,32 +56,34 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
render.ubo_align = @intCast(buffer_align_int);
// MESH VAO
var vao: gl.GLuint = 0;
gl.createVertexArrays(1, &vao);
std.debug.assert(vao != 0);
render.mesh_vao = vao;
{
// MESH VAO
var vao: gl.GLuint = 0;
gl.createVertexArrays(1, &vao);
std.debug.assert(vao != 0);
render.mesh_vao = vao;
// positions
// gl.vertexArrayVertexBuffer(vao, 0, vertices, 0, @sizeOf(formats.Vector3));
gl.enableVertexArrayAttrib(vao, Attrib.Position.value());
gl.vertexArrayAttribBinding(vao, Attrib.Position.value(), 0);
gl.vertexArrayAttribFormat(vao, Attrib.Position.value(), 3, gl.FLOAT, gl.FALSE, 0);
// positions
// gl.vertexArrayVertexBuffer(vao, 0, vertices, 0, @sizeOf(formats.Vector3));
gl.enableVertexArrayAttrib(vao, Attrib.Position.value());
gl.vertexArrayAttribBinding(vao, Attrib.Position.value(), 0);
gl.vertexArrayAttribFormat(vao, Attrib.Position.value(), 3, gl.FLOAT, gl.FALSE, 0);
// normals
gl.enableVertexArrayAttrib(vao, Attrib.Normal.value());
gl.vertexArrayAttribBinding(vao, Attrib.Normal.value(), 1);
gl.vertexArrayAttribFormat(vao, Attrib.Normal.value(), 3, gl.FLOAT, gl.FALSE, 0);
// normals
gl.enableVertexArrayAttrib(vao, Attrib.Normal.value());
gl.vertexArrayAttribBinding(vao, Attrib.Normal.value(), 1);
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);
// 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
gl.enableVertexArrayAttrib(vao, Attrib.UV.value());
gl.vertexArrayAttribBinding(vao, Attrib.UV.value(), 2);
gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0);
// uvs
gl.enableVertexArrayAttrib(vao, Attrib.UV.value());
gl.vertexArrayAttribBinding(vao, Attrib.UV.value(), 2);
gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0);
}
const PERSISTENT_BUFFER_FLAGS: gl.GLbitfield = gl.MAP_PERSISTENT_BIT | gl.MAP_WRITE_BIT | gl.MAP_COHERENT_BIT;
@ -124,20 +135,70 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
render.point_lights = point_lights_c[0..buf_size];
}
{
// Shadow texture array
gl.createTextures(gl.TEXTURE_2D_ARRAY, 1, &render.shadow_texture_arrray);
checkGLError();
std.debug.assert(render.shadow_texture_arrray != 0);
gl.textureStorage3D(render.shadow_texture_arrray, 1, gl.DEPTH_COMPONENT16, 1024, 1024, 1);
checkGLError();
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
//gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.textureParameteri(render.shadow_texture_arrray, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// First shadow texture handle
render.shadow_texture_handle = gl.GL_ARB_bindless_texture.getTextureHandleARB(render.shadow_texture_arrray);
checkGLError();
gl.GL_ARB_bindless_texture.makeTextureHandleResidentARB(render.shadow_texture_handle);
checkGLError();
// Shadow FBO
gl.createFramebuffers(1, &render.shadow_framebuffer);
checkGLError();
std.debug.assert(render.shadow_framebuffer != 0);
gl.namedFramebufferTextureLayer(render.shadow_framebuffer, gl.DEPTH_ATTACHMENT, render.shadow_texture_arrray, 0, 0);
const check_fbo_status = gl.checkNamedFramebufferStatus(render.shadow_framebuffer, gl.DRAW_FRAMEBUFFER);
if (check_fbo_status != gl.FRAMEBUFFER_COMPLETE) {
std.log.debug("Shadow Framebuffer Incomplete: {}\n", .{check_fbo_status});
}
gl.createBuffers(1, &render.shadow_matrices_buffer);
gl.namedBufferStorage(
render.shadow_matrices_buffer,
@sizeOf(CameraMatrices),
null,
gl.DYNAMIC_STORAGE_BIT,
);
// SHADOW VAO
var vao: gl.GLuint = 0;
gl.createVertexArrays(1, &vao);
std.debug.assert(vao != 0);
render.shadow_vao = vao;
// positions
// gl.vertexArrayVertexBuffer(vao, 0, vertices, 0, @sizeOf(formats.Vector3));
gl.enableVertexArrayAttrib(vao, Attrib.Position.value());
gl.vertexArrayAttribBinding(vao, Attrib.Position.value(), 0);
gl.vertexArrayAttribFormat(vao, Attrib.Position.value(), 3, gl.FLOAT, gl.FALSE, 0);
}
return render;
}
pub fn begin(self: *Render) void {
self.command_count = 0;
self.tripple_buffer_index = (self.tripple_buffer_index + 1) % MAX_FRAMES_QUEUED;
gl.enable(gl.CULL_FACE);
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.mesh).program);
gl.bindVertexArray(self.mesh_vao);
if (self.gl_fences[self.tripple_buffer_index]) |fence| {
const syncResult = gl.clientWaitSync(fence, gl.SYNC_FLUSH_COMMANDS_BIT, 9999999999);
@ -170,25 +231,6 @@ pub fn getPointLights(self: *Render) *PointLightArray {
pub fn flushUBOs(self: *Render) void {
const idx = self.tripple_buffer_index;
{
const camera_matrix: *CameraMatrices = @alignCast(@ptrCast(self.camera_matrices[idx * self.uboAlignedSizeOf(CameraMatrices) ..].ptr));
camera_matrix.* = .{
.projection = self.camera.projection(),
.view = self.camera.view_mat,
};
//gl.flushMappedNamedBufferRange(self.camera_ubo, idx * @sizeOf(CameraMatrices), @sizeOf(CameraMatrices));
gl.bindBufferRange(
gl.UNIFORM_BUFFER,
UBO.CameraMatrices.value(),
self.camera_ubo,
idx * self.uboAlignedSizeOf(CameraMatrices),
@intCast(self.uboAlignedSizeOf(CameraMatrices)),
);
checkGLError();
}
// gl.flushMappedNamedBufferRange(self.point_lights_ubo, idx * @sizeOf(PointLightArray), @sizeOf(PointLightArray));
gl.bindBufferRange(
gl.UNIFORM_BUFFER,
@ -201,76 +243,173 @@ pub fn flushUBOs(self: *Render) void {
}
pub fn draw(self: *Render, cmd: DrawCommand) void {
const mesh = self.assetman.resolveMesh(cmd.mesh);
const material: Material = if (cmd.material_override) |mat| mat else mesh.material;
gl.uniformMatrix4fv(Uniform.ModelMatrix.value(), 1, gl.FALSE, @ptrCast(&cmd.transform.data));
{
gl.uniform3fv(Uniform.Color.value(), 1, @ptrCast(&material.albedo.data));
const albedo_map = self.assetman.resolveTexture(material.albedo_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.AlbedoMap.value(),
albedo_map.handle,
);
gl.uniform2fv(Uniform.AlbedoMapUVScale.value(), 1, @ptrCast(&albedo_map.uv_scale.data));
}
{
const normal_map = self.assetman.resolveTexture(material.normal_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.NormalMap.value(),
normal_map.handle,
);
gl.uniform2fv(Uniform.NormalMapUVScale.value(), 1, @ptrCast(&normal_map.uv_scale.data));
}
{
gl.uniform1fv(Uniform.Metallic.value(), 1, &material.metallic);
const metallic_map = self.assetman.resolveTexture(material.metallic_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.MetallicMap.value(),
metallic_map.handle,
);
gl.uniform2fv(Uniform.MetallicMapUVScale.value(), 1, @ptrCast(&metallic_map.uv_scale.data));
}
{
gl.uniform1fv(Uniform.Roughness.value(), 1, &material.roughness);
const roughness_map = self.assetman.resolveTexture(material.roughness_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.RoughnessMap.value(),
roughness_map.handle,
);
gl.uniform2fv(Uniform.RoughnessMapUVScale.value(), 1, @ptrCast(&roughness_map.uv_scale.data));
}
{
gl.uniform1fv(Uniform.Emission.value(), 1, &material.emission);
const emission_map = self.assetman.resolveTexture(material.emission_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.EmissionMap.value(),
emission_map.handle,
);
gl.uniform2fv(Uniform.EmissionMapUVScale.value(), 1, @ptrCast(&emission_map.uv_scale.data));
}
mesh.positions.bind(Render.Attrib.Position.value());
mesh.normals.bind(Render.Attrib.Normal.value());
mesh.tangents.bind(Render.Attrib.Tangent.value());
mesh.uvs.bind(Render.Attrib.UV.value());
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indices.buffer);
gl.drawElements(
gl.TRIANGLES,
mesh.indices.count,
mesh.indices.type,
@ptrFromInt(mesh.indices.offset),
);
self.command_buffer[self.command_count] = cmd;
self.command_count += 1;
}
pub fn finish(self: *Render) void {
const ginit = globals.g_init;
var dir_light: ?PointLight = null;
var dir_light_vp: ?Mat4 = null;
// Find directional light
{
const lights = self.getPointLights();
for (lights.lights[0..lights.count]) |*light| {
if (std.math.approxEqAbs(f32, light.pos.w(), 0, std.math.floatEps(f32))) {
dir_light = light.*;
}
// Transform view to camera view space
light.pos = self.camera.view_mat.mulByVec4(light.pos);
}
}
// Directional Light shadow map
if (dir_light) |light| {
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, self.shadow_framebuffer);
gl.viewport(0, 0, 1024, 1024);
gl.clear(gl.DEPTH_BUFFER_BIT);
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.shadow).program);
gl.bindVertexArray(self.shadow_vao);
const camera_matrix = &self.shadow_matrices;
camera_matrix.* = .{
.projection = Mat4.orthographic(-5, 5, -5, 5, -10, 10),
.view = Mat4.lookAt(
Vec3.new(light.pos.x(), light.pos.y(), light.pos.z()).scale(-1),
Vec3.zero(),
Vec3.up(),
),
};
dir_light_vp = camera_matrix.projection.mul(camera_matrix.view);
// TODO: use multiple buffers for this in the future
gl.namedBufferSubData(self.shadow_matrices_buffer, 0, @sizeOf(CameraMatrices), std.mem.asBytes(camera_matrix));
checkGLError();
gl.bindBufferBase(gl.UNIFORM_BUFFER, UBO.CameraMatrices.value(), self.shadow_matrices_buffer);
for (self.command_buffer[0..self.command_count]) |*cmd| {
const mesh = self.assetman.resolveMesh(cmd.mesh);
gl.uniformMatrix4fv(Uniform.ModelMatrix.value(), 1, gl.FALSE, @ptrCast(&cmd.transform.data));
mesh.positions.bind(Render.Attrib.Position.value());
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indices.buffer);
gl.drawElements(
gl.TRIANGLES,
mesh.indices.count,
mesh.indices.type,
@ptrFromInt(mesh.indices.offset),
);
}
}
var width: c_int = 0;
var height: c_int = 0;
c.SDL_GL_GetDrawableSize(globals.g_init.window, &width, &height);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, 0);
gl.viewport(0, 0, width, height);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
{
const camera_matrix: *CameraMatrices = @alignCast(@ptrCast(self.camera_matrices[self.tripple_buffer_index * self.uboAlignedSizeOf(CameraMatrices) ..].ptr));
camera_matrix.* = .{
.projection = self.camera.projection(),
.view = self.camera.view_mat,
};
//gl.flushMappedNamedBufferRange(self.camera_ubo, idx * @sizeOf(CameraMatrices), @sizeOf(CameraMatrices));
gl.bindBufferRange(
gl.UNIFORM_BUFFER,
UBO.CameraMatrices.value(),
self.camera_ubo,
self.tripple_buffer_index * self.uboAlignedSizeOf(CameraMatrices),
@intCast(self.uboAlignedSizeOf(CameraMatrices)),
);
checkGLError();
}
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.mesh).program);
gl.bindVertexArray(self.mesh_vao);
for (self.command_buffer[0..self.command_count]) |*cmd| {
const mesh = self.assetman.resolveMesh(cmd.mesh);
const material: Material = if (cmd.material_override) |mat| mat else mesh.material;
gl.uniformMatrix4fv(Uniform.ModelMatrix.value(), 1, gl.FALSE, @ptrCast(&cmd.transform.data));
{
gl.uniform3fv(Uniform.Color.value(), 1, @ptrCast(&material.albedo.data));
const albedo_map = self.assetman.resolveTexture(material.albedo_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.AlbedoMap.value(),
albedo_map.handle,
);
gl.uniform2fv(Uniform.AlbedoMapUVScale.value(), 1, @ptrCast(&albedo_map.uv_scale.data));
}
{
const normal_map = self.assetman.resolveTexture(material.normal_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.NormalMap.value(),
normal_map.handle,
);
gl.uniform2fv(Uniform.NormalMapUVScale.value(), 1, @ptrCast(&normal_map.uv_scale.data));
}
{
gl.uniform1fv(Uniform.Metallic.value(), 1, &material.metallic);
const metallic_map = self.assetman.resolveTexture(material.metallic_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.MetallicMap.value(),
metallic_map.handle,
);
gl.uniform2fv(Uniform.MetallicMapUVScale.value(), 1, @ptrCast(&metallic_map.uv_scale.data));
}
{
gl.uniform1fv(Uniform.Roughness.value(), 1, &material.roughness);
const roughness_map = self.assetman.resolveTexture(material.roughness_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.RoughnessMap.value(),
roughness_map.handle,
);
gl.uniform2fv(Uniform.RoughnessMapUVScale.value(), 1, @ptrCast(&roughness_map.uv_scale.data));
}
{
gl.uniform1fv(Uniform.Emission.value(), 1, &material.emission);
const emission_map = self.assetman.resolveTexture(material.emission_map);
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(
Uniform.EmissionMap.value(),
emission_map.handle,
);
gl.uniform2fv(Uniform.EmissionMapUVScale.value(), 1, @ptrCast(&emission_map.uv_scale.data));
}
if (dir_light != null) {
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(Uniform.ShadowMap.value(), self.shadow_texture_handle);
gl.uniformMatrix4fv(Uniform.ShadowMapVP.value(), 1, gl.FALSE, @ptrCast(&dir_light_vp.?.data));
}
mesh.positions.bind(Render.Attrib.Position.value());
mesh.normals.bind(Render.Attrib.Normal.value());
mesh.tangents.bind(Render.Attrib.Tangent.value());
mesh.uvs.bind(Render.Attrib.UV.value());
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indices.buffer);
gl.drawElements(
gl.TRIANGLES,
mesh.indices.count,
mesh.indices.type,
@ptrFromInt(mesh.indices.offset),
);
}
self.gl_fences[self.tripple_buffer_index] = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
c.SDL_GL_SwapWindow(ginit.window);
c.SDL_Delay(1);
@ -343,6 +482,9 @@ pub const Uniform = enum(gl.GLint) {
EmissionMap = 14,
EmissionMapUVScale = 15,
ShadowMap = 16,
ShadowMapVP = 17,
pub inline fn value(self: Uniform) gl.GLint {
return @intFromEnum(self);
}
@ -364,8 +506,8 @@ pub const Camera = struct {
// Should be std140
const CameraMatrices = extern struct {
projection: Mat4,
view: Mat4,
projection: Mat4 = Mat4.identity(),
view: Mat4 = Mat4.identity(),
};
pub const PointLight = extern struct {
pos: Vec4, // x, y, z, w - vPos

View File

@ -51,6 +51,7 @@ pub const Entity = struct {
pub fn rotate(self: *Transform, axis: Vec3, angle: f32) void {
self.rot = self.rot.mul(Quat.fromAxis(angle, axis));
self.rot = self.rot.norm();
self.dirty();
}
};

View File

@ -113,7 +113,7 @@ fn loadGL() void {
@panic("gl.load");
};
gl.debugMessageCallback(glDebugCallback, null);
//gl.enable(gl.DEBUG_OUTPUT);
// gl.enable(gl.DEBUG_OUTPUT);
}
fn glDebugCallback(source: gl.GLenum, _type: gl.GLenum, id: gl.GLuint, severity: gl.GLenum, length: gl.GLsizei, message: [*:0]const u8, userParam: ?*anyopaque) callconv(.C) void {
@ -186,9 +186,10 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
gl.viewport(0, 0, globals.g_init.width, globals.g_init.height);
_ = globals.g_mem.world.addEntity(.{
.flags = .{ .dir_light = true },
.flags = .{ .dir_light = true, .rotate = true },
.transform = .{ .rot = Quat.fromEulerAngles(Vec3.new(60, 15, 0)) },
.light = .{ .color_intensity = Vec4.new(1, 1, 0.83, 1) },
.rotate = .{ .rate = 45, .axis = Vec3.up() },
});
const light_root = globals.g_mem.world.addEntity(.{
@ -224,7 +225,7 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
// Plane
_ = globals.g_mem.world.addEntity(.{
.flags = .{ .mesh = true },
.transform = .{ .scale = Vec3.one().scale(2) },
.transform = .{ .scale = Vec3.one().scale(10) },
.mesh = .{
.handle = a.Meshes.plane.Plane,
.material = .{
@ -442,7 +443,6 @@ export fn game_update() bool {
if (ent.data.flags.point_light) {
const pos = ent.globalMatrix(&gmem.world).extractTranslation();
var pos4 = Vec4.new(pos.x(), pos.y(), pos.z(), 1.0);
pos4 = gmem.render.camera.view_mat.mulByVec4(pos4);
const color = ent.data.light.premultipliedColor();
point_lights.lights[point_lights.count] = .{
@ -455,8 +455,7 @@ export fn game_update() bool {
}
}
if (ent.data.flags.dir_light) {
var dir4 = ent.globalMatrix(&gmem.world).mulByVec4(Vec4.forward());
dir4 = gmem.render.camera.view_mat.mulByVec4(dir4);
const dir4 = ent.globalMatrix(&gmem.world).mulByVec4(Vec4.forward());
const color = ent.data.light.premultipliedColor();
point_lights.lights[point_lights.count] = .{
.pos = dir4,

View File

@ -576,7 +576,6 @@ const TextureType = enum {
};
fn processTexture(allocator: std.mem.Allocator, texture_type: TextureType, contents: []const u8, out_file: std.fs.File) !void {
const format = if (texture_type == .Normal) formats.Texture.Format.bc5 else formats.Texture.Format.bc7;
var width_int: c_int = 0;
var height_int: c_int = 0;
var comps: c_int = 0;
@ -588,6 +587,14 @@ fn processTexture(allocator: std.mem.Allocator, texture_type: TextureType, conte
}
defer c.stbi_image_free(rgba_data_c);
var format = formats.Texture.Format.bc7;
// TODO: bc4
if (comps == 1) {}
if (texture_type == .Normal or comps == 2) {
format = .bc5;
}
const width: usize = @intCast(width_int);
const height: usize = @intCast(height_int);