2020-08-11 12:07:21 -04:00
|
|
|
#include "shadowpass.hpp"
|
|
|
|
|
|
|
|
#include "gfx_commandbuffer.hpp"
|
|
|
|
#include "scene.hpp"
|
|
|
|
#include "gfx.hpp"
|
|
|
|
#include "log.hpp"
|
|
|
|
#include "engine.hpp"
|
2020-08-15 20:09:16 -04:00
|
|
|
#include "materialcompiler.hpp"
|
2020-08-11 12:07:21 -04:00
|
|
|
#include "assertions.hpp"
|
|
|
|
#include "frustum.hpp"
|
2020-09-21 09:37:52 -04:00
|
|
|
#include "renderer.hpp"
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
struct PushConstant {
|
|
|
|
Matrix4x4 mvp, model;
|
|
|
|
};
|
|
|
|
|
|
|
|
const std::array<Matrix4x4, 6> shadowTransforms = {
|
2020-08-19 17:15:00 -04:00
|
|
|
transform::look_at(Vector3(0), Vector3(1.0, 0.0, 0.0), Vector3(0.0, 1.0, 0.0)), // right
|
|
|
|
transform::look_at(Vector3(0), Vector3(-1.0, 0.0, 0.0), Vector3(0.0, 1.0, 0.0)), // left
|
|
|
|
transform::look_at(Vector3(0), Vector3( 0.0, 1.0, 0.0), Vector3(0.0, 0.0, -1.0)), // top
|
|
|
|
transform::look_at(Vector3(0), Vector3( 0.0, -1.0, 0.0), Vector3(0.0, 0.0, 1.0)), // bottom
|
|
|
|
transform::look_at(Vector3(0), Vector3( 0.0, 0.0, 1.0), Vector3(0.0, 1.0, 0.0)), // back
|
|
|
|
transform::look_at(Vector3(0), Vector3( 0.0, 0.0, -1.0), Vector3(0.0, 1.0, 0.0)) // front
|
2020-08-11 12:07:21 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
ShadowPass::ShadowPass(GFX* gfx) {
|
|
|
|
Expects(gfx != nullptr);
|
|
|
|
Expects(render_options.shadow_resolution > 0);
|
|
|
|
|
|
|
|
create_render_passes();
|
|
|
|
create_pipelines();
|
|
|
|
create_offscreen_resources();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowPass::create_scene_resources(Scene& scene) {
|
|
|
|
auto gfx = engine->get_gfx();
|
|
|
|
|
|
|
|
// sun light
|
|
|
|
{
|
|
|
|
GFXTextureCreateInfo textureInfo = {};
|
2021-02-04 08:21:40 -05:00
|
|
|
textureInfo.label = "Shadow Depth";
|
2020-08-11 12:07:21 -04:00
|
|
|
textureInfo.width = render_options.shadow_resolution;
|
|
|
|
textureInfo.height = render_options.shadow_resolution;
|
|
|
|
textureInfo.format = GFXPixelFormat::DEPTH_32F;
|
|
|
|
textureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::Attachment;
|
|
|
|
|
|
|
|
scene.depthTexture = gfx->create_texture(textureInfo);
|
|
|
|
|
|
|
|
GFXFramebufferCreateInfo info;
|
|
|
|
info.attachments = {scene.depthTexture};
|
|
|
|
info.render_pass = render_pass;
|
|
|
|
|
|
|
|
scene.framebuffer = gfx->create_framebuffer(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
// point lights
|
|
|
|
if(gfx->supports_feature(GFXFeature::CubemapArray)) {
|
|
|
|
GFXTextureCreateInfo cubeTextureInfo = {};
|
2021-02-04 08:21:40 -05:00
|
|
|
cubeTextureInfo.label = "Point Light Array";
|
2020-08-11 12:07:21 -04:00
|
|
|
cubeTextureInfo.type = GFXTextureType::CubemapArray;
|
|
|
|
cubeTextureInfo.width = render_options.shadow_resolution;
|
|
|
|
cubeTextureInfo.height = render_options.shadow_resolution;
|
|
|
|
cubeTextureInfo.format = GFXPixelFormat::R_32F;
|
|
|
|
cubeTextureInfo.usage = GFXTextureUsage::Sampled;
|
|
|
|
cubeTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
|
|
|
cubeTextureInfo.array_length = max_point_shadows;
|
|
|
|
|
|
|
|
scene.pointLightArray = gfx->create_texture(cubeTextureInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
// spot lights
|
|
|
|
{
|
|
|
|
GFXTextureCreateInfo spotTextureInfo = {};
|
2021-02-04 08:21:40 -05:00
|
|
|
spotTextureInfo.label = "Spot Light Array";
|
2020-08-11 12:07:21 -04:00
|
|
|
spotTextureInfo.type = GFXTextureType::Array2D;
|
|
|
|
spotTextureInfo.width = render_options.shadow_resolution;
|
|
|
|
spotTextureInfo.height = render_options.shadow_resolution;
|
|
|
|
spotTextureInfo.format = GFXPixelFormat::DEPTH_32F;
|
|
|
|
spotTextureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::Attachment;
|
|
|
|
spotTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
|
|
|
spotTextureInfo.array_length = max_spot_shadows;
|
|
|
|
|
|
|
|
scene.spotLightArray = gfx->create_texture(spotTextureInfo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowPass::render(GFXCommandBuffer* command_buffer, Scene& scene) {
|
|
|
|
last_spot_light = 0;
|
|
|
|
last_point_light = 0;
|
2021-04-18 22:14:19 -04:00
|
|
|
|
|
|
|
if(scene.shadow_refresh_timer > 0) {
|
|
|
|
scene.shadow_refresh_timer--;
|
|
|
|
return;
|
|
|
|
}
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
auto lights = scene.get_all<Light>();
|
|
|
|
for(auto [obj, light] : lights) {
|
|
|
|
switch(light.type) {
|
|
|
|
case Light::Type::Sun:
|
|
|
|
render_sun(command_buffer, scene, obj, light);
|
|
|
|
break;
|
|
|
|
case Light::Type::Spot:
|
|
|
|
render_spot(command_buffer, scene, obj, light);
|
|
|
|
break;
|
|
|
|
case Light::Type::Point:
|
|
|
|
render_point(command_buffer, scene, obj, light);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-23 09:53:45 -04:00
|
|
|
void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, const Matrix4x4 light_matrix, const Matrix4x4 model, const Vector3 light_position, const Light::Type type, const CameraFrustum& frustum, const int base_instance) {
|
2020-08-11 12:07:21 -04:00
|
|
|
for(auto [obj, mesh] : scene.get_all<Renderable>()) {
|
|
|
|
if(!mesh.mesh)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
command_buffer->set_vertex_buffer(mesh.mesh->position_buffer, 0, position_buffer_index);
|
|
|
|
|
|
|
|
command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32);
|
|
|
|
|
|
|
|
PushConstant pc;
|
|
|
|
pc.mvp = light_matrix * model * scene.get<Transform>(obj).model;
|
|
|
|
pc.model = scene.get<Transform>(obj).model;
|
|
|
|
|
|
|
|
if(mesh.mesh->bones.empty()) {
|
|
|
|
switch(type) {
|
|
|
|
case Light::Type::Sun:
|
2020-09-22 16:09:25 -04:00
|
|
|
command_buffer->set_graphics_pipeline(static_sun_pipeline);
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
case Light::Type::Spot:
|
2020-09-22 16:09:25 -04:00
|
|
|
command_buffer->set_graphics_pipeline(static_spot_pipeline);
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
case Light::Type::Point:
|
2020-09-22 16:09:25 -04:00
|
|
|
command_buffer->set_graphics_pipeline(static_point_pipeline);
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-09-30 19:18:17 -04:00
|
|
|
command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(Vector3) * max_point_shadows);
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
|
|
|
|
command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f);
|
|
|
|
|
|
|
|
for (auto& part : mesh.mesh->parts) {
|
2020-08-17 10:11:58 -04:00
|
|
|
if(render_options.enable_frustum_culling && !test_aabb_frustum(frustum, get_aabb_for_part(scene.get<Transform>(obj), part)))
|
2020-08-11 12:07:21 -04:00
|
|
|
continue;
|
|
|
|
|
2020-09-23 09:53:45 -04:00
|
|
|
command_buffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, base_instance);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch(type) {
|
|
|
|
case Light::Type::Sun:
|
2020-09-22 16:09:25 -04:00
|
|
|
command_buffer->set_graphics_pipeline(skinned_sun_pipeline);
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
case Light::Type::Spot:
|
2020-09-22 16:09:25 -04:00
|
|
|
command_buffer->set_graphics_pipeline(skinned_spot_pipeline);
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
case Light::Type::Point:
|
2020-09-22 16:09:25 -04:00
|
|
|
command_buffer->set_graphics_pipeline(skinned_point_pipeline);
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
}
|
2020-09-30 19:18:17 -04:00
|
|
|
|
|
|
|
command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(Vector3) * max_point_shadows);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
|
|
|
|
|
|
|
|
command_buffer->set_vertex_buffer(mesh.mesh->bone_buffer, 0, bone_buffer_index);
|
|
|
|
command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f);
|
|
|
|
|
|
|
|
for (auto& part : mesh.mesh->parts) {
|
2020-08-17 10:11:58 -04:00
|
|
|
if(render_options.enable_frustum_culling && !test_aabb_frustum(frustum, get_aabb_for_part(scene.get<Transform>(obj), part)))
|
2020-08-11 12:07:21 -04:00
|
|
|
continue;
|
|
|
|
|
2020-09-23 11:54:59 -04:00
|
|
|
command_buffer->bind_shader_buffer(part.bone_batrix_buffer, 0, 14, sizeof(Matrix4x4) * 128);
|
2020-09-23 09:53:45 -04:00
|
|
|
command_buffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, base_instance);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowPass::render_sun(GFXCommandBuffer* command_buffer, Scene& scene, Object light_object, Light& light) {
|
|
|
|
if(scene.sun_light_dirty || light.use_dynamic_shadows) {
|
|
|
|
GFXRenderPassBeginInfo info = {};
|
|
|
|
info.framebuffer = scene.framebuffer;
|
|
|
|
info.render_pass = render_pass;
|
|
|
|
info.render_area.extent = {static_cast<uint32_t>(render_options.shadow_resolution), static_cast<uint32_t>(render_options.shadow_resolution)};
|
|
|
|
|
|
|
|
command_buffer->set_render_pass(info);
|
|
|
|
|
|
|
|
Viewport viewport = {};
|
|
|
|
viewport.width = render_options.shadow_resolution;
|
|
|
|
viewport.height = render_options.shadow_resolution;
|
|
|
|
|
|
|
|
command_buffer->set_viewport(viewport);
|
|
|
|
|
|
|
|
const Vector3 lightPos = scene.get<Transform>(light_object).position;
|
|
|
|
|
|
|
|
const Matrix4x4 projection = transform::orthographic(-25.0f, 25.0f, -25.0f, 25.0f, 0.1f, 100.0f);
|
|
|
|
const Matrix4x4 view = transform::look_at(lightPos, Vector3(0), Vector3(0, 1, 0));
|
|
|
|
|
2020-08-18 00:35:49 -04:00
|
|
|
const Matrix4x4 realMVP = projection * view;
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2020-08-18 00:35:49 -04:00
|
|
|
scene.lightSpace = projection;
|
|
|
|
scene.lightSpace[1][1] *= -1;
|
|
|
|
scene.lightSpace = scene.lightSpace * view;
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
const auto frustum = normalize_frustum(extract_frustum(projection * view));
|
|
|
|
|
|
|
|
if(light.enable_shadows)
|
2020-09-23 09:53:45 -04:00
|
|
|
render_meshes(command_buffer, scene, realMVP, Matrix4x4(), lightPos, Light::Type::Sun, frustum, 0);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
scene.sun_light_dirty = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowPass::render_spot(GFXCommandBuffer* command_buffer, Scene& scene, Object light_object, Light& light) {
|
|
|
|
if((last_spot_light + 1) == max_spot_shadows)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(scene.spot_light_dirty[last_spot_light] || light.use_dynamic_shadows) {
|
|
|
|
GFXRenderPassBeginInfo info = {};
|
|
|
|
info.framebuffer = offscreen_framebuffer;
|
|
|
|
info.render_pass = cube_render_pass;
|
|
|
|
info.render_area.extent = {static_cast<uint32_t>(render_options.shadow_resolution), static_cast<uint32_t>(render_options.shadow_resolution)};
|
|
|
|
|
|
|
|
command_buffer->set_render_pass(info);
|
|
|
|
|
|
|
|
Viewport viewport = {};
|
|
|
|
viewport.width = render_options.shadow_resolution;
|
|
|
|
viewport.height = render_options.shadow_resolution;
|
|
|
|
|
|
|
|
command_buffer->set_viewport(viewport);
|
|
|
|
|
2020-08-18 00:35:49 -04:00
|
|
|
const Matrix4x4 perspective = transform::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2020-08-18 00:35:49 -04:00
|
|
|
const Matrix4x4 realMVP = perspective * inverse(scene.get<Transform>(light_object).model);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2020-08-18 00:35:49 -04:00
|
|
|
scene.spotLightSpaces[last_spot_light] = perspective;
|
2020-08-19 17:19:20 -04:00
|
|
|
scene.spotLightSpaces[last_spot_light][1][1] *= -1;
|
2020-08-18 00:35:49 -04:00
|
|
|
scene.spotLightSpaces[last_spot_light] = scene.spotLightSpaces[last_spot_light] * inverse(scene.get<Transform>(light_object).model);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
const auto frustum = normalize_frustum(extract_frustum(perspective * inverse(scene.get<Transform>(light_object).model)));
|
|
|
|
|
|
|
|
if(light.enable_shadows)
|
2020-09-23 09:53:45 -04:00
|
|
|
render_meshes(command_buffer, scene, realMVP, Matrix4x4(), scene.get<Transform>(light_object).get_world_position(), Light::Type::Spot, frustum, 0);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-02-15 17:59:54 -05:00
|
|
|
command_buffer->end_render_pass();
|
2020-08-11 12:07:21 -04:00
|
|
|
command_buffer->copy_texture(offscreen_depth, render_options.shadow_resolution, render_options.shadow_resolution, scene.spotLightArray, 0, last_spot_light, 0);
|
|
|
|
|
|
|
|
scene.spot_light_dirty[last_spot_light] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
last_spot_light++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, Object light_object, Light& light) {
|
|
|
|
if(!render_options.enable_point_shadows)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if((last_point_light + 1) == max_point_shadows)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(scene.point_light_dirty[last_point_light] || light.use_dynamic_shadows) {
|
2020-09-23 09:53:45 -04:00
|
|
|
*(point_location_map + last_point_light) = scene.get<Transform>(light_object).get_world_position();
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
for(int face = 0; face < 6; face++) {
|
|
|
|
GFXRenderPassBeginInfo info = {};
|
|
|
|
info.framebuffer = offscreen_framebuffer;
|
|
|
|
info.render_pass = cube_render_pass;
|
|
|
|
info.render_area.extent = {static_cast<uint32_t>(render_options.shadow_resolution), static_cast<uint32_t>(render_options.shadow_resolution)};
|
|
|
|
|
|
|
|
command_buffer->set_render_pass(info);
|
|
|
|
|
|
|
|
Viewport viewport = {};
|
|
|
|
viewport.width = render_options.shadow_resolution;
|
|
|
|
viewport.height = render_options.shadow_resolution;
|
|
|
|
|
|
|
|
command_buffer->set_viewport(viewport);
|
|
|
|
|
|
|
|
const Vector3 lightPos = scene.get<Transform>(light_object).get_world_position();
|
|
|
|
|
2020-08-18 00:35:49 -04:00
|
|
|
const Matrix4x4 projection = transform::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f);
|
|
|
|
const Matrix4x4 model = inverse(scene.get<Transform>(light_object).model);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
const auto frustum = normalize_frustum(extract_frustum(projection * shadowTransforms[face] * model));
|
|
|
|
|
2020-09-23 09:53:45 -04:00
|
|
|
render_meshes(command_buffer, scene, projection * shadowTransforms[face], model, lightPos, Light::Type::Point, frustum, last_point_light);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-02-15 17:59:54 -05:00
|
|
|
command_buffer->end_render_pass();
|
2020-08-11 12:07:21 -04:00
|
|
|
command_buffer->copy_texture(offscreen_color_texture, render_options.shadow_resolution, render_options.shadow_resolution, scene.pointLightArray, face, last_point_light, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
scene.point_light_dirty[last_point_light] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
last_point_light++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowPass::create_render_passes() {
|
|
|
|
auto gfx = engine->get_gfx();
|
|
|
|
|
|
|
|
// render pass
|
|
|
|
GFXRenderPassCreateInfo renderPassInfo = {};
|
2020-09-23 10:17:24 -04:00
|
|
|
renderPassInfo.label = "Shadow";
|
2020-08-11 12:07:21 -04:00
|
|
|
renderPassInfo.attachments.push_back(GFXPixelFormat::DEPTH_32F);
|
2021-02-15 19:01:17 -05:00
|
|
|
renderPassInfo.will_use_in_shader = true;
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
render_pass = gfx->create_render_pass(renderPassInfo);
|
|
|
|
|
2020-09-23 10:17:24 -04:00
|
|
|
renderPassInfo.label = "Shadow Cube";
|
2020-08-11 12:07:21 -04:00
|
|
|
renderPassInfo.attachments.clear();
|
|
|
|
renderPassInfo.attachments.push_back(GFXPixelFormat::R_32F);
|
|
|
|
renderPassInfo.attachments.push_back(GFXPixelFormat::DEPTH_32F);
|
|
|
|
|
|
|
|
cube_render_pass = gfx->create_render_pass(renderPassInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowPass::create_pipelines() {
|
2020-09-23 09:53:45 -04:00
|
|
|
GFXShaderConstant point_light_max_constant = {};
|
|
|
|
point_light_max_constant.value = max_point_shadows;
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
2020-09-23 09:53:45 -04:00
|
|
|
pipelineInfo.shaders.vertex_constants = {point_light_max_constant};
|
2021-05-12 08:50:02 -04:00
|
|
|
pipelineInfo.shaders.vertex_src = ShaderSource(prism::Path("shadow.vert"));
|
2020-09-23 09:53:45 -04:00
|
|
|
|
|
|
|
pipelineInfo.shaders.fragment_constants = { point_light_max_constant };
|
2021-05-09 19:10:23 -04:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
pipelineInfo.shader_input.bindings = {
|
2020-09-23 09:53:45 -04:00
|
|
|
{0, GFXBindingType::PushConstant},
|
|
|
|
{1, GFXBindingType::StorageBuffer},
|
|
|
|
{2, GFXBindingType::StorageBuffer}
|
2020-08-11 12:07:21 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
pipelineInfo.shader_input.push_constants = {
|
|
|
|
{sizeof(PushConstant), 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
pipelineInfo.render_pass = render_pass;
|
|
|
|
|
|
|
|
pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual;
|
2020-08-18 00:35:49 -04:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
// sun
|
|
|
|
{
|
|
|
|
pipelineInfo.label = "Sun Shadow";
|
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
static_sun_pipeline = static_pipeline;
|
|
|
|
skinned_sun_pipeline = skinned_pipeline;
|
|
|
|
}
|
|
|
|
|
|
|
|
// spot
|
|
|
|
{
|
|
|
|
pipelineInfo.label = "Spot Shadow";
|
|
|
|
|
|
|
|
pipelineInfo.render_pass = cube_render_pass;
|
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
static_spot_pipeline = static_pipeline;
|
|
|
|
skinned_spot_pipeline = skinned_pipeline;
|
|
|
|
}
|
|
|
|
|
|
|
|
// point
|
|
|
|
{
|
|
|
|
pipelineInfo.label = "Point Shadow";
|
|
|
|
|
2021-05-12 08:50:02 -04:00
|
|
|
pipelineInfo.shaders.fragment_src = ShaderSource(prism::Path("omnishadow.frag"));
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
static_point_pipeline = static_pipeline;
|
|
|
|
skinned_point_pipeline = skinned_pipeline;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowPass::create_offscreen_resources() {
|
|
|
|
auto gfx = engine->get_gfx();
|
|
|
|
|
|
|
|
GFXTextureCreateInfo textureInfo = {};
|
2021-02-04 08:21:40 -05:00
|
|
|
textureInfo.label = "Shadow Color";
|
2020-08-11 12:07:21 -04:00
|
|
|
textureInfo.width = render_options.shadow_resolution;
|
|
|
|
textureInfo.height = render_options.shadow_resolution;
|
|
|
|
textureInfo.format = GFXPixelFormat::R_32F;
|
2021-05-11 19:16:54 -04:00
|
|
|
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
2020-08-11 12:07:21 -04:00
|
|
|
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
2021-05-11 19:16:54 -04:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
offscreen_color_texture = gfx->create_texture(textureInfo);
|
|
|
|
|
|
|
|
GFXTextureCreateInfo depthTextureInfo = {};
|
2021-02-04 08:21:40 -05:00
|
|
|
depthTextureInfo.label = "Shadow Depth";
|
2020-08-11 12:07:21 -04:00
|
|
|
depthTextureInfo.width = render_options.shadow_resolution;
|
|
|
|
depthTextureInfo.height = render_options.shadow_resolution;
|
|
|
|
depthTextureInfo.format = GFXPixelFormat::DEPTH_32F;
|
2021-05-11 19:16:54 -04:00
|
|
|
depthTextureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
2020-08-11 12:07:21 -04:00
|
|
|
depthTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
|
|
|
|
|
|
|
offscreen_depth = gfx->create_texture(depthTextureInfo);
|
|
|
|
|
|
|
|
GFXFramebufferCreateInfo info;
|
|
|
|
info.attachments = {offscreen_color_texture, offscreen_depth};
|
2020-09-23 11:54:59 -04:00
|
|
|
info.render_pass = cube_render_pass;
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
offscreen_framebuffer = gfx->create_framebuffer(info);
|
2020-09-23 09:53:45 -04:00
|
|
|
|
|
|
|
point_location_buffer = gfx->create_buffer(nullptr, sizeof(Vector3) * max_point_shadows, false, GFXBufferUsage::Storage);
|
|
|
|
point_location_map = reinterpret_cast<Vector3*>(gfx->get_buffer_contents(point_location_buffer));
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|