Basic directional shadow map
This commit is contained in:
parent
aec4a4a882
commit
73501f7991
@ -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);
|
||||
|
||||
|
28
assets/shaders/shadow.glsl
Normal file
28
assets/shaders/shadow.glsl
Normal 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
|
6
assets/shaders/shadow.prog
Normal file
6
assets/shaders/shadow.prog
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
{
|
||||
"shader": "shadow.glsl",
|
||||
"vertex": true,
|
||||
"fragment": true
|
||||
}
|
370
src/Render.zig
370
src/Render.zig
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
11
src/game.zig
11
src/game.zig
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user