Browse Source

Add support for loading shader templates. Begin to phase out direct loading of shader programs in favor of shader templates.

master
C. J. Howard 1 year ago
parent
commit
4c2993b3fe
16 changed files with 132 additions and 226 deletions
  1. +0
    -1
      src/game/state/boot.cpp
  2. +29
    -10
      src/render/passes/bloom-pass.cpp
  3. +4
    -0
      src/render/passes/bloom-pass.hpp
  4. +10
    -1
      src/render/passes/final-pass.cpp
  5. +3
    -0
      src/render/passes/final-pass.hpp
  6. +10
    -2
      src/render/passes/fxaa-pass.cpp
  7. +2
    -0
      src/render/passes/fxaa-pass.hpp
  8. +10
    -2
      src/render/passes/resample-pass.cpp
  9. +2
    -0
      src/render/passes/resample-pass.hpp
  10. +0
    -117
      src/render/passes/simple-pass.cpp
  11. +0
    -71
      src/render/passes/simple-pass.hpp
  12. +17
    -4
      src/render/passes/sky-pass.cpp
  13. +3
    -8
      src/render/passes/sky-pass.hpp
  14. +6
    -2
      src/render/shader-template.cpp
  15. +16
    -7
      src/render/shader-template.hpp
  16. +20
    -1
      src/resources/shader-loader.cpp

+ 0
- 1
src/game/state/boot.cpp View File

@ -50,7 +50,6 @@
#include "render/passes/shadow-map-pass.hpp"
#include "render/passes/sky-pass.hpp"
#include "render/passes/ground-pass.hpp"
#include "render/passes/simple-pass.hpp"
#include "render/vertex-attribute.hpp"
#include "render/compositor.hpp"
#include "render/renderer.hpp"

+ 29
- 10
src/render/passes/bloom-pass.cpp View File

@ -45,19 +45,30 @@ bloom_pass::bloom_pass(gl::rasterizer* rasterizer, resource_manager* resource_ma
filter_radius(0.005f),
corrected_filter_radius{filter_radius, filter_radius}
{
// Load downsample shader with Karis average
downsample_karis_shader = resource_manager->load<gl::shader_program>("bloom-downsample-karis.glsl");
// Load downsample shader template
downsample_shader_template = resource_manager->load<shader_template>("bloom-downsample.glsl");
// Build downsample shader program with Karis averaging
downsample_karis_shader = downsample_shader_template->build
(
{
{"KARIS_AVERAGE", std::string()}
}
);
downsample_karis_source_texture_input = downsample_karis_shader->get_input("source_texture");
// Load downsample shader
downsample_shader = resource_manager->load<gl::shader_program>("bloom-downsample.glsl");
// Build downsample shader program without Karis averaging
downsample_shader = downsample_shader_template->build();
downsample_source_texture_input = downsample_shader->get_input("source_texture");
// Load upsample shader
upsample_shader = resource_manager->load<gl::shader_program>("bloom-upsample.glsl");
// Load upsample shader template
upsample_shader_template = resource_manager->load<shader_template>("bloom-upsample.glsl");
// Build upsample shader program
upsample_shader = upsample_shader_template->build();
upsample_source_texture_input = upsample_shader->get_input("source_texture");
upsample_filter_radius_input = upsample_shader->get_input("filter_radius");
const float vertex_data[] =
{
-1.0f, 1.0f,
@ -71,7 +82,7 @@ bloom_pass::bloom_pass(gl::rasterizer* rasterizer, resource_manager* resource_ma
std::size_t vertex_size = 2;
std::size_t vertex_stride = sizeof(float) * vertex_size;
std::size_t vertex_count = 6;
quad_vbo = new gl::vertex_buffer(sizeof(float) * vertex_size * vertex_count, vertex_data);
quad_vao = new gl::vertex_array();
@ -89,10 +100,18 @@ bloom_pass::bloom_pass(gl::rasterizer* rasterizer, resource_manager* resource_ma
bloom_pass::~bloom_pass()
{
set_mip_chain_length(0);
delete quad_vao;
delete quad_vbo;
set_mip_chain_length(0);
delete downsample_karis_shader;
delete downsample_shader;
delete upsample_shader;
/// @TODO
//resource_manager->unload("bloom-downsample.glsl");
//resource_manager->unload("bloom-upsample.glsl");
}
void bloom_pass::render(const render::context& ctx, render::queue& queue) const

+ 4
- 0
src/render/passes/bloom-pass.hpp View File

@ -21,6 +21,7 @@
#define ANTKEEPER_RENDER_BLOOM_PASS_HPP
#include "render/pass.hpp"
#include "render/shader-template.hpp"
#include "gl/shader-program.hpp"
#include "gl/shader-input.hpp"
#include "gl/vertex-buffer.hpp"
@ -95,6 +96,9 @@ public:
private:
const gl::texture_2d* source_texture;
shader_template* downsample_shader_template;
shader_template* upsample_shader_template;
gl::shader_program* downsample_karis_shader;
const gl::shader_input* downsample_karis_source_texture_input;

+ 10
- 1
src/render/passes/final-pass.cpp View File

@ -45,7 +45,11 @@ final_pass::final_pass(gl::rasterizer* rasterizer, const gl::framebuffer* frameb
blue_noise_texture(nullptr),
blue_noise_scale(1.0f)
{
shader_program = resource_manager->load<gl::shader_program>("final.glsl");
// Load shader template
shader_template = resource_manager->load<render::shader_template>("final.glsl");
// Build shader program
shader_program = shader_template->build();
color_texture_input = shader_program->get_input("color_texture");
bloom_texture_input = shader_program->get_input("bloom_texture");
bloom_weight_input = shader_program->get_input("bloom_weight");
@ -87,6 +91,11 @@ final_pass::~final_pass()
{
delete quad_vao;
delete quad_vbo;
delete shader_program;
/// @TODO
// resource_manager->unload("final.glsl");
}
void final_pass::render(const render::context& ctx, render::queue& queue) const

+ 3
- 0
src/render/passes/final-pass.hpp View File

@ -21,6 +21,7 @@
#define ANTKEEPER_RENDER_FINAL_PASS_HPP
#include "render/pass.hpp"
#include "render/shader-template.hpp"
#include "gl/shader-program.hpp"
#include "gl/shader-input.hpp"
#include "gl/vertex-buffer.hpp"
@ -47,6 +48,8 @@ public:
void set_blue_noise_texture(const gl::texture_2d* texture);
private:
render::shader_template* shader_template;
gl::shader_program* shader_program;
const gl::shader_input* color_texture_input;
const gl::shader_input* bloom_texture_input;

+ 10
- 2
src/render/passes/fxaa-pass.cpp View File

@ -38,8 +38,11 @@ fxaa_pass::fxaa_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuf
pass(rasterizer, framebuffer),
source_texture(nullptr)
{
// Load FXAA shader
shader = resource_manager->load<gl::shader_program>("fxaa.glsl");
// Load FXAA shader template
shader_template = resource_manager->load<render::shader_template>("fxaa.glsl");
// Build FXAA shader program
shader = shader_template->build();
source_texture_input = shader->get_input("source_texture");
texel_size_input = shader->get_input("texel_size");
@ -76,6 +79,11 @@ fxaa_pass::~fxaa_pass()
{
delete quad_vao;
delete quad_vbo;
delete shader;
/// @TODO
// resource_manager->unload("fxaa.glsl");
}
void fxaa_pass::render(const render::context& ctx, render::queue& queue) const

+ 2
- 0
src/render/passes/fxaa-pass.hpp View File

@ -21,6 +21,7 @@
#define ANTKEEPER_RENDER_FXAA_PASS_HPP
#include "render/pass.hpp"
#include "render/shader-template.hpp"
#include "gl/shader-program.hpp"
#include "gl/shader-input.hpp"
#include "gl/vertex-buffer.hpp"
@ -71,6 +72,7 @@ public:
private:
const gl::texture_2d* source_texture;
render::shader_template* shader_template;
gl::shader_program* shader;
const gl::shader_input* source_texture_input;
const gl::shader_input* texel_size_input;

+ 10
- 2
src/render/passes/resample-pass.cpp View File

@ -38,8 +38,11 @@ resample_pass::resample_pass(gl::rasterizer* rasterizer, const gl::framebuffer*
pass(rasterizer, framebuffer),
source_texture(nullptr)
{
// Load resample shader
shader = resource_manager->load<gl::shader_program>("resample.glsl");
// Load resample shader template
shader_template = resource_manager->load<render::shader_template>("resample.glsl");
// Build resample shader program
shader = shader_template->build();
source_texture_input = shader->get_input("source_texture");
const float vertex_data[] =
@ -75,6 +78,11 @@ resample_pass::~resample_pass()
{
delete quad_vao;
delete quad_vbo;
delete shader;
/// @TODO
// resource_manager->unload("resample.glsl");
}
void resample_pass::render(const render::context& ctx, render::queue& queue) const

+ 2
- 0
src/render/passes/resample-pass.hpp View File

@ -21,6 +21,7 @@
#define ANTKEEPER_RENDER_RESAMPLE_PASS_HPP
#include "render/pass.hpp"
#include "render/shader-template.hpp"
#include "gl/shader-program.hpp"
#include "gl/shader-input.hpp"
#include "gl/vertex-buffer.hpp"
@ -69,6 +70,7 @@ public:
private:
const gl::texture_2d* source_texture;
render::shader_template* shader_template;
gl::shader_program* shader;
const gl::shader_input* source_texture_input;

+ 0
- 117
src/render/passes/simple-pass.cpp View File

@ -1,117 +0,0 @@
/*
* Copyright (C) 2023 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "render/passes/simple-pass.hpp"
#include "gl/rasterizer.hpp"
#include "gl/framebuffer.hpp"
#include "gl/shader-program.hpp"
#include "gl/shader-input.hpp"
#include "gl/vertex-buffer.hpp"
#include "gl/vertex-array.hpp"
#include "gl/vertex-attribute.hpp"
#include "gl/drawing-mode.hpp"
#include "gl/texture-2d.hpp"
#include "gl/texture-wrapping.hpp"
#include "gl/texture-filter.hpp"
#include "render/vertex-attribute.hpp"
#include "render/context.hpp"
#include "render/material.hpp"
#include "render/material-property.hpp"
#include <glad/glad.h>
namespace render {
simple_pass::simple_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffer, gl::shader_program* shader_program):
pass(rasterizer, framebuffer),
shader_program(shader_program)
{
// Create material
material = new render::material(shader_program);
// Add standard properties to material
time_property = material->add_property<float>("time");
resolution_property = material->add_property<float2>("resolution");
const float vertex_data[] =
{
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f
};
std::size_t vertex_size = 3;
std::size_t vertex_stride = sizeof(float) * vertex_size;
std::size_t vertex_count = 6;
quad_vbo = new gl::vertex_buffer(sizeof(float) * vertex_size * vertex_count, vertex_data);
quad_vao = new gl::vertex_array();
// Define position vertex attribute
gl::vertex_attribute position_attribute;
position_attribute.buffer = quad_vbo;
position_attribute.offset = 0;
position_attribute.stride = vertex_stride;
position_attribute.type = gl::vertex_attribute_type::float_32;
position_attribute.components = 3;
// Bind vertex attributes to VAO
quad_vao->bind(render::vertex_attribute::position, position_attribute);
}
simple_pass::~simple_pass()
{
delete material;
delete quad_vao;
delete quad_vbo;
}
void simple_pass::render(const render::context& ctx, render::queue& queue) const
{
// Bind framebuffer
rasterizer->use_framebuffer(*framebuffer);
// Setup graphics context
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// Setup viewport
auto viewport = framebuffer->get_dimensions();
rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport));
// Change shader program
rasterizer->use_program(*shader_program);
// Update material properties
time_property->set_value(ctx.t);
resolution_property->set_value({static_cast<float>(std::get<0>(viewport)), static_cast<float>(std::get<1>(viewport))});
// Upload material properties
material->upload(ctx.alpha);
// Draw quad
rasterizer->draw_arrays(*quad_vao, gl::drawing_mode::triangles, 0, 6);
}
} // namespace render

+ 0
- 71
src/render/passes/simple-pass.hpp View File

@ -1,71 +0,0 @@
/*
* Copyright (C) 2023 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_RENDER_SIMPLE_PASS_HPP
#define ANTKEEPER_RENDER_SIMPLE_PASS_HPP
#include "render/pass.hpp"
#include "utility/fundamental-types.hpp"
#include "gl/shader-program.hpp"
#include "gl/shader-input.hpp"
#include "gl/vertex-buffer.hpp"
#include "gl/vertex-array.hpp"
namespace render {
class material;
template <class T>
class material_property;
/**
* Simple render passes are associated with a single shader and a single material.
*/
class simple_pass: public pass
{
public:
simple_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffer, gl::shader_program* shader_program);
virtual ~simple_pass();
virtual void render(const render::context& ctx, render::queue& queue) const final;
const render::material* get_material() const;
render::material* get_material();
private:
gl::shader_program* shader_program;
material* material;
material_property<float>* time_property;
material_property<float2>* resolution_property;
gl::vertex_buffer* quad_vbo;
gl::vertex_array* quad_vao;
};
inline const render::material* simple_pass::get_material() const
{
return material;
}
inline render::material* simple_pass::get_material()
{
return material;
}
} // namespace render
#endif // ANTKEEPER_RENDER_SIMPLE_PASS_HPP

+ 17
- 4
src/render/passes/sky-pass.cpp View File

@ -114,8 +114,11 @@ sky_pass::sky_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffe
transmittance_lut_framebuffer->attach(gl::framebuffer_attachment_type::color, transmittance_lut_texture);
transmittance_lut_resolution = {static_cast<float>(transmittance_lut_texture->get_width()), static_cast<float>(transmittance_lut_texture->get_height())};
// Load transmittance LUT shader
transmittance_shader_program = resource_manager->load<gl::shader_program>("transmittance-lut.glsl");
// Load transmittance LUT shader template
transmittance_shader_template = resource_manager->load<render::shader_template>("transmittance-lut.glsl");
// Build transmittance LUT shader program
transmittance_shader_program = transmittance_shader_template->build();
transmittance_atmosphere_radii_input = transmittance_shader_program->get_input("atmosphere_radii");
transmittance_rayleigh_parameters_input = transmittance_shader_program->get_input("rayleigh_parameters");
transmittance_mie_parameters_input = transmittance_shader_program->get_input("mie_parameters");
@ -134,8 +137,11 @@ sky_pass::sky_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffe
sky_lut_framebuffer = new gl::framebuffer(sky_lut_width, sky_lut_height);
sky_lut_framebuffer->attach(gl::framebuffer_attachment_type::color, sky_lut_texture);
// Load sky LUT shader
sky_lut_shader_program = resource_manager->load<gl::shader_program>("sky-illuminance-lut.glsl");
// Load sky LUT shader template
sky_lut_shader_template = resource_manager->load<render::shader_template>("sky-illuminance-lut.glsl");
// Build sky LUT shader program
sky_lut_shader_program = sky_lut_shader_template->build();
sky_lut_light_direction_input = sky_lut_shader_program->get_input("light_direction");
sky_lut_light_illuminance_input = sky_lut_shader_program->get_input("light_illuminance");
sky_lut_atmosphere_radii_input = sky_lut_shader_program->get_input("atmosphere_radii");
@ -158,6 +164,13 @@ sky_pass::~sky_pass()
delete transmittance_lut_texture;
delete quad_vao;
delete quad_vbo;
delete transmittance_shader_program;
delete sky_lut_shader_program;
/// @TODO
// resource_maanger->unload("transmittance-lut.glsl");
// resource_maanger->unload("sky-illuminance-lut.glsl");
}
void sky_pass::render(const render::context& ctx, render::queue& queue) const

+ 3
- 8
src/render/passes/sky-pass.hpp View File

@ -21,6 +21,7 @@
#define ANTKEEPER_RENDER_SKY_PASS_HPP
#include "render/pass.hpp"
#include "render/shader-template.hpp"
#include "utility/fundamental-types.hpp"
#include "event/event-handler.hpp"
#include "event/input-events.hpp"
@ -101,6 +102,7 @@ private:
gl::texture_2d* transmittance_lut_texture;
gl::framebuffer* transmittance_lut_framebuffer;
float2 transmittance_lut_resolution;
render::shader_template* transmittance_shader_template;
gl::shader_program* transmittance_shader_program;
const gl::shader_input* transmittance_atmosphere_radii_input;
const gl::shader_input* transmittance_rayleigh_parameters_input;
@ -112,6 +114,7 @@ private:
gl::texture_2d* sky_lut_texture;
gl::framebuffer* sky_lut_framebuffer;
render::shader_template* sky_lut_shader_template;
gl::shader_program* sky_lut_shader_program;
float2 sky_lut_resolution;
const gl::shader_input* sky_lut_light_direction_input;
@ -174,13 +177,6 @@ private:
const gl::shader_input* star_projection_input;
const gl::shader_input* star_exposure_input;
const gl::shader_input* star_distance_input;
gl::shader_program* cloud_shader_program;
const gl::shader_input* cloud_model_view_projection_input;
const gl::shader_input* cloud_sun_direction_input;
const gl::shader_input* cloud_sun_illuminance_input;
const gl::shader_input* cloud_camera_position_input;
const gl::shader_input* cloud_camera_exposure_input;
float2 mouse_position;
@ -200,7 +196,6 @@ private:
tween<float3> moon_planetlight_illuminance_tween;
tween<float3> moon_illuminance_tween;
float3 moon_transmitted_illuminance;
float sun_angular_radius;
float atmosphere_upper_limit;

+ 6
- 2
src/render/shader-template.cpp View File

@ -28,7 +28,8 @@ shader_template::shader_template(const std::string& source_code)
source(source_code);
}
shader_template::shader_template()
shader_template::shader_template():
hash(std::hash<std::string>{}(std::string()))
{}
void shader_template::source(const std::string& source)
@ -71,6 +72,9 @@ void shader_template::source(const std::string& source)
// Append line to template source
template_source.push_back(line);
}
// Calculate hash of source
hash = std::hash<std::string>{}(source);
}
std::string shader_template::configure(gl::shader_stage stage, const dictionary_type& definitions) const
@ -186,7 +190,7 @@ void shader_template::replace_define_directives(const dictionary_type& definitio
auto definitions_it = definitions.find(define_directive.first);
if (definitions_it != definitions.end())
{
// Definition found, Replace `#pragma define <key>` with `#define <key>` or `#define <key> <value>`
// Definition found, replace `#pragma define <key>` with `#define <key>` or `#define <key> <value>`
line = "#define " + define_directive.first;
if (!definitions_it->second.empty())
line += " " + definitions_it->second;

+ 16
- 7
src/render/shader-template.hpp View File

@ -30,7 +30,7 @@
namespace render {
/**
* Shader templates can be used to generate multiple shader variants from a single source.
* Template used to for generating one or more shader variants from a single source.
*
* Shader templates support the following preprocessor directives:
*
@ -46,11 +46,11 @@ namespace render {
class shader_template
{
public:
/// Container of definitions used to replace `#pragma define <key> <value>` directives.
/// Container of definitions used to generate `#pragma define <key> <value>` directives.
typedef std::unordered_map<std::string, std::string> dictionary_type;
/**
* Creates a shader template and sets its source code.
* Constructs a shader template and sets its source code.
*
* @param source_code String containing the shader template source code.
*
@ -59,7 +59,7 @@ public:
shader_template(const std::string& source_code);
/**
* Creates a shader template.
* Constructs an empty shader template.
*/
shader_template();
@ -77,7 +77,7 @@ public:
* @param definitions Container of definitions used to replace `#pragma define <key> <value>` directives.
* @return Configured shader object source code.
*/
std::string configure(gl::shader_stage stage, const dictionary_type& definitions) const;
std::string configure(gl::shader_stage stage, const dictionary_type& definitions = {}) const;
/**
* Configures and compiles a shader object.
@ -88,7 +88,7 @@ public:
*
* @exception std::runtime_error Any exceptions thrown by gl::shader_object.
*/
gl::shader_object* compile(gl::shader_stage stage, const dictionary_type& definitions) const;
gl::shader_object* compile(gl::shader_stage stage, const dictionary_type& definitions = {}) const;
/**
* Configures and compiles shader objects, then links them into a shader program. Shader object stages are determined according to the presence of `#pragma <stage>` directives.
@ -102,7 +102,7 @@ public:
* @see has_fragment_directive() const
* @see has_geometry_directive() const
*/
gl::shader_program* build(const dictionary_type& definitions) const;
gl::shader_program* build(const dictionary_type& definitions = {}) const;
/// Returns `true` if the template source contains one or more `#pragma vertex` directive.
bool has_vertex_directive() const;
@ -120,6 +120,9 @@ public:
*/
bool has_define_directive(const std::string& key) const;
/// Returns a hash of the template source.
std::size_t get_hash() const;
private:
void replace_stage_directives(gl::shader_stage stage) const;
void replace_define_directives(const dictionary_type& definitions) const;
@ -129,8 +132,14 @@ private:
std::unordered_set<std::size_t> fragment_directives;
std::unordered_set<std::size_t> geometry_directives;
std::multimap<std::string, std::size_t> define_directives;
std::size_t hash;
};
inline std::size_t shader_template::get_hash() const
{
return hash;
}
} // namespace render
#endif // ANTKEEPER_RENDER_SHADER_TEMPLATE_HPP

src/resources/shader-program-loader.cpp → src/resources/shader-loader.cpp View File

@ -102,6 +102,25 @@ gl::shader_program* resource_loader::load(resource_manager*
// Destroy shader template
delete shader;
return program;
}
template <>
render::shader_template* resource_loader<render::shader_template>::load(resource_manager* resource_manager, PHYSFS_File* file, const std::filesystem::path& path)
{
// Load shader template source
text_file source_lines = *resource_loader<text_file>::load(resource_manager, file, path);
// Handle `#pragma include` directives
handle_includes(&source_lines, resource_manager);
// Join vector of source lines into single string
std::ostringstream stream;
std::copy(source_lines.begin(), source_lines.end(), std::ostream_iterator<std::string>(stream, "\n"));
// Create shader template
render::shader_template* shader = new render::shader_template(stream.str());
return shader;
}

Loading…
Cancel
Save