2020-08-15 20:09:16 -04:00
|
|
|
#include "materialcompiler.hpp"
|
2020-08-11 12:07:21 -04:00
|
|
|
|
|
|
|
#include "file.hpp"
|
|
|
|
#include "log.hpp"
|
|
|
|
#include "engine.hpp"
|
|
|
|
#include "string_utils.hpp"
|
2020-08-15 20:09:16 -04:00
|
|
|
#include "shadercompiler.hpp"
|
2020-09-21 09:37:52 -04:00
|
|
|
#include "renderer.hpp"
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2021-10-14 08:51:58 -04:00
|
|
|
ShaderSource get_shader(const std::string& filename, bool skinned, bool cubemap) {
|
2022-05-21 18:28:48 -04:00
|
|
|
auto shader_file = prism::open_file(prism::base_domain / filename);
|
2020-08-14 20:53:22 -04:00
|
|
|
if(!shader_file.has_value()) {
|
2021-09-13 23:41:54 -04:00
|
|
|
prism::log("Failed to open shader file {}!", filename);
|
2020-08-15 20:32:02 -04:00
|
|
|
return {};
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
ShaderStage stage;
|
2020-08-11 12:07:21 -04:00
|
|
|
if(filename.find("vert") != std::string::npos) {
|
2020-08-15 20:09:16 -04:00
|
|
|
stage = ShaderStage::Vertex;
|
2020-08-11 12:07:21 -04:00
|
|
|
} else {
|
2020-08-15 20:09:16 -04:00
|
|
|
stage = ShaderStage::Fragment;
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
CompileOptions options;
|
|
|
|
if(skinned)
|
|
|
|
options.add_definition("BONE");
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
if(cubemap)
|
|
|
|
options.add_definition("CUBEMAP");
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2021-05-09 19:10:23 -04:00
|
|
|
return *shader_compiler.compile(ShaderLanguage::GLSL, stage, ShaderSource(shader_file->read_as_string()), engine->get_gfx()->accepted_shader_language(), options);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
GFXPipeline* MaterialCompiler::create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only, bool cubemap) {
|
2020-08-11 12:07:21 -04:00
|
|
|
// take vertex src
|
2022-02-21 15:57:38 -05:00
|
|
|
const std::string vertex_path = fmt::format("{}.glsl", createInfo.shaders.vertex_src.as_path().string());
|
2020-09-30 19:18:17 -04:00
|
|
|
|
|
|
|
if (positions_only)
|
2022-02-21 13:20:55 -05:00
|
|
|
createInfo.label += " (shadow)";
|
2020-09-30 19:18:17 -04:00
|
|
|
|
|
|
|
if (cubemap)
|
2022-02-21 13:20:55 -05:00
|
|
|
createInfo.label += " (cubemap)";
|
|
|
|
|
2020-08-14 17:45:51 -04:00
|
|
|
createInfo.shaders.vertex_src = get_shader(vertex_path, false, cubemap);
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
if(positions_only) {
|
|
|
|
createInfo.vertex_input.inputs = {
|
2021-05-12 09:56:44 -04:00
|
|
|
{position_buffer_index, sizeof(prism::float3)}
|
2020-08-11 12:07:21 -04:00
|
|
|
};
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
createInfo.vertex_input.attributes = {
|
|
|
|
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3}
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
createInfo.vertex_input.inputs = {
|
2021-05-12 09:56:44 -04:00
|
|
|
{position_buffer_index, sizeof(prism::float3)},
|
|
|
|
{normal_buffer_index, sizeof(prism::float3)},
|
|
|
|
{texcoord_buffer_index, sizeof(prism::float2)},
|
|
|
|
{tangent_buffer_index, sizeof(prism::float3)},
|
|
|
|
{bitangent_buffer_index, sizeof(prism::float3)}
|
2020-08-11 12:07:21 -04:00
|
|
|
};
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
createInfo.vertex_input.attributes = {
|
|
|
|
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3},
|
|
|
|
{normal_buffer_index, 1, 0, GFXVertexFormat::FLOAT3},
|
|
|
|
{texcoord_buffer_index, 2, 0, GFXVertexFormat::FLOAT2},
|
|
|
|
{tangent_buffer_index, 3, 0, GFXVertexFormat::FLOAT3},
|
|
|
|
{bitangent_buffer_index, 4, 0, GFXVertexFormat::FLOAT3}
|
|
|
|
};
|
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
return engine->get_gfx()->create_graphics_pipeline(createInfo);
|
|
|
|
}
|
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
GFXPipeline* MaterialCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only) {
|
2022-02-21 13:20:55 -05:00
|
|
|
createInfo.label += " (skinned)";
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
// take vertex src
|
2022-02-21 13:20:55 -05:00
|
|
|
const std::string vertex_path = fmt::format("{}.glsl", createInfo.shaders.vertex_src.as_path().string());
|
|
|
|
|
2020-08-14 17:45:51 -04:00
|
|
|
createInfo.shaders.vertex_src = get_shader(vertex_path, true, false);
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-09-23 11:54:59 -04:00
|
|
|
createInfo.shader_input.bindings.push_back({ 14, GFXBindingType::StorageBuffer });
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
if(positions_only) {
|
|
|
|
createInfo.vertex_input.inputs = {
|
2021-05-12 09:56:44 -04:00
|
|
|
{position_buffer_index, sizeof(prism::float3)},
|
2020-08-11 12:07:21 -04:00
|
|
|
{bone_buffer_index, sizeof(BoneVertexData)}
|
|
|
|
};
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
createInfo.vertex_input.attributes = {
|
|
|
|
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3},
|
|
|
|
{bone_buffer_index, 4, offsetof(BoneVertexData, ids), GFXVertexFormat::INT4},
|
|
|
|
{bone_buffer_index, 5, offsetof(BoneVertexData, weights), GFXVertexFormat::FLOAT4}
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
createInfo.vertex_input.inputs = {
|
2021-05-12 09:56:44 -04:00
|
|
|
{position_buffer_index, sizeof(prism::float3)},
|
|
|
|
{normal_buffer_index, sizeof(prism::float3)},
|
|
|
|
{texcoord_buffer_index, sizeof(prism::float2)},
|
|
|
|
{tangent_buffer_index, sizeof(prism::float3)},
|
|
|
|
{bitangent_buffer_index, sizeof(prism::float3)},
|
2020-08-11 12:07:21 -04:00
|
|
|
{bone_buffer_index, sizeof(BoneVertexData)}
|
|
|
|
};
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
createInfo.vertex_input.attributes = {
|
|
|
|
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3},
|
|
|
|
{normal_buffer_index, 1, 0, GFXVertexFormat::FLOAT3},
|
|
|
|
{texcoord_buffer_index, 2, 0, GFXVertexFormat::FLOAT2},
|
|
|
|
{tangent_buffer_index, 3, 0, GFXVertexFormat::FLOAT3},
|
|
|
|
{bitangent_buffer_index, 4, 0, GFXVertexFormat::FLOAT3},
|
|
|
|
{bone_buffer_index, 5, offsetof(BoneVertexData, ids), GFXVertexFormat::INT4},
|
|
|
|
{bone_buffer_index, 6, offsetof(BoneVertexData, weights), GFXVertexFormat::FLOAT4},
|
|
|
|
};
|
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
return engine->get_gfx()->create_graphics_pipeline(createInfo);
|
|
|
|
}
|
|
|
|
|
2020-08-15 20:09:16 -04:00
|
|
|
std::tuple<GFXPipeline*, GFXPipeline*> MaterialCompiler::create_pipeline_permutations(GFXGraphicsPipelineCreateInfo& createInfo, bool positions_only) {
|
2020-08-11 12:07:21 -04:00
|
|
|
auto st = create_static_pipeline(createInfo, positions_only);
|
|
|
|
auto ss = create_skinned_pipeline(createInfo, positions_only);
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
return {st, ss};
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr std::string_view struct_info =
|
2022-03-10 10:21:09 -05:00
|
|
|
R"(layout (constant_id = 0) const int max_materials = 25;
|
|
|
|
layout (constant_id = 1) const int max_lights = 25;
|
|
|
|
layout (constant_id = 2) const int max_spot_lights = 4;
|
|
|
|
layout (constant_id = 3) const int max_probes = 4;
|
|
|
|
struct Material {{
|
2022-02-21 13:20:55 -05:00
|
|
|
vec4 color, info;
|
|
|
|
}};
|
|
|
|
struct Light {{
|
|
|
|
vec4 positionType;
|
|
|
|
vec4 directionPower;
|
|
|
|
vec4 colorSize;
|
|
|
|
vec4 shadowsEnable;
|
|
|
|
}};
|
|
|
|
struct Probe {{
|
|
|
|
vec4 position, size;
|
|
|
|
}};
|
|
|
|
layout(std430, binding = 1) buffer readonly SceneInformation {{
|
|
|
|
vec4 options;
|
|
|
|
vec4 camPos;
|
|
|
|
mat4 vp, lightSpace;
|
2022-03-10 10:21:09 -05:00
|
|
|
mat4 spotLightSpaces[max_spot_lights];
|
|
|
|
Material materials[max_materials];
|
|
|
|
Light lights[max_lights];
|
|
|
|
Probe probes[max_probes];
|
2022-02-21 13:20:55 -05:00
|
|
|
int numLights;
|
|
|
|
}} scene;
|
2022-03-10 10:21:03 -05:00
|
|
|
layout (binding = 2) uniform sampler2D sun_shadow;
|
|
|
|
layout (binding = 6) uniform sampler2DArray spot_shadow;
|
2022-02-21 13:20:55 -05:00
|
|
|
layout(push_constant) uniform PushConstant {{
|
|
|
|
mat4 model;
|
|
|
|
}};
|
|
|
|
)";
|
2020-08-11 12:07:21 -04:00
|
|
|
|
2020-08-15 20:32:02 -04:00
|
|
|
ShaderSource MaterialCompiler::compile_material_fragment(Material& material, bool use_ibl) {
|
2020-08-11 12:07:21 -04:00
|
|
|
if(!render_options.enable_ibl)
|
|
|
|
use_ibl = false;
|
2022-02-21 13:20:55 -05:00
|
|
|
|
|
|
|
auto src = fmt::memory_buffer();
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
switch(render_options.shadow_filter) {
|
|
|
|
case ShadowFilter::None:
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), "#define SHADOW_FILTER_NONE\n");
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
case ShadowFilter::PCF:
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), "#define SHADOW_FILTER_PCF\n");
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
case ShadowFilter::PCSS:
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), "#define SHADOW_FILTER_PCSS\n");
|
2020-08-11 12:07:21 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(layout (location = 0) in vec3 in_frag_pos;
|
|
|
|
layout(location = 1) in vec3 in_normal;
|
|
|
|
layout(location = 2) in vec2 in_uv;
|
|
|
|
layout(location = 0) out vec4 frag_output;
|
|
|
|
)");
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
if(render_options.enable_point_shadows) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(#define POINT_SHADOWS_SUPPORTED
|
2022-03-10 10:21:03 -05:00
|
|
|
layout (binding = 3) uniform samplerCubeArray point_shadow;
|
2022-02-21 13:20:55 -05:00
|
|
|
)");
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
|
|
|
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), struct_info);
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
if(use_ibl) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
2022-03-10 10:21:03 -05:00
|
|
|
R"(layout (binding = 7) uniform samplerCubeArray irrandianceSampler;
|
|
|
|
layout (binding = 8) uniform samplerCubeArray prefilterSampler;
|
|
|
|
layout (binding = 9) uniform sampler2D brdfSampler;
|
2022-02-21 13:20:55 -05:00
|
|
|
)");
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(layout(location = 4) in vec4 fragPosLightSpace;
|
|
|
|
layout(location = 5) in mat3 in_tbn;
|
2022-03-10 10:21:09 -05:00
|
|
|
layout(location = 14) in vec4 fragPostSpotLightSpace[max_spot_lights];
|
2022-02-21 13:20:55 -05:00
|
|
|
layout(location = 13) in flat int inMaterialIndex;
|
|
|
|
#include "common.glsl"
|
|
|
|
#include "rendering.glsl"
|
|
|
|
)");
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
material.bound_textures.clear();
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
// insert samplers as needed
|
2022-03-10 10:21:03 -05:00
|
|
|
int sampler_index = 10;
|
2022-02-03 10:00:59 -05:00
|
|
|
if(material.colorProperty.type == DataType::AssetTexture) {
|
|
|
|
material.bound_textures[sampler_index] = material.colorProperty.value_tex;
|
|
|
|
|
2022-03-10 10:21:03 -05:00
|
|
|
format_to(std::back_inserter(src), "layout(binding = {}) uniform sampler2D colorTexture;\n", sampler_index++);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
2022-02-15 09:02:42 -05:00
|
|
|
|
|
|
|
if(material.normalProperty.type == DataType::AssetTexture) {
|
|
|
|
material.bound_textures[sampler_index] = material.normalProperty.value_tex;
|
|
|
|
|
2022-03-10 10:21:03 -05:00
|
|
|
format_to(std::back_inserter(src), "layout(binding = {}) uniform sampler2D normalTexture;\n", sampler_index++);
|
2022-02-15 09:02:42 -05:00
|
|
|
}
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
if(use_ibl) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(vec3 get_reflect(int i, vec3 final_normal) {{
|
|
|
|
const vec3 direction = normalize(in_frag_pos - scene.camPos.xyz);
|
|
|
|
const vec3 reflection = reflect(direction, normalize(final_normal));
|
|
|
|
vec3 box_max = scene.probes[i].position.xyz + (scene.probes[i].size.xyz / 2.0f);
|
|
|
|
vec3 box_min = scene.probes[i].position.xyz + -(scene.probes[i].size.xyz / 2.0f);
|
|
|
|
vec3 unitary = vec3(1.0);
|
|
|
|
vec3 first_plane_intersect = (box_max - in_frag_pos) / reflection;
|
|
|
|
vec3 second_plane_intersect = (box_min - in_frag_pos) / reflection;
|
|
|
|
vec3 furthest_plane = max(first_plane_intersect, second_plane_intersect);
|
|
|
|
float distance = min(furthest_plane.x, min(furthest_plane.y, furthest_plane.z));
|
|
|
|
vec3 intersect_position_world = in_frag_pos + reflection * distance;
|
|
|
|
return intersect_position_world - scene.probes[i].position.xyz;
|
|
|
|
}}
|
|
|
|
)");
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
if(render_options.enable_normal_shadowing) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(float calculate_normal_lighting(in sampler2D normal_map, const vec3 normal, const vec3 light_dir) {{
|
|
|
|
float height_scale = 0.8;
|
|
|
|
float sample_count = 100.0;
|
|
|
|
float inv_sample_count = 1.0 / sample_count;
|
|
|
|
float hardness = 50 * 0.5;
|
|
|
|
float lighting = clamp(dot(light_dir, normal), 0.0, 1.0);
|
|
|
|
float slope = -lighting;
|
|
|
|
vec2 dir = light_dir.xy * vec2(1.0, -1.0) * height_scale;
|
|
|
|
float max_slope = 0.0;
|
|
|
|
float step = inv_sample_count;
|
|
|
|
float pos = step;
|
|
|
|
pos = (-lighting >= 0.0) ? 1.001 : pos;
|
|
|
|
vec2 noise = fract(in_frag_pos.xy * 0.5);
|
|
|
|
noise.x = noise.x + noise.y * 0.5;
|
|
|
|
pos = step - step * noise.x;
|
|
|
|
float shadow = 0.0;
|
|
|
|
while(pos <= 1.0) {{
|
2022-03-10 10:21:03 -05:00
|
|
|
vec3 tmp_normal = texture(normal_map, in_uv + dir * pos).rgb;
|
2022-02-21 13:20:55 -05:00
|
|
|
tmp_normal = in_tbn * (tmp_normal * 2.0 - 1.0);
|
|
|
|
float tmp_lighting = dot(light_dir, tmp_normal);
|
|
|
|
float shadowed = -tmp_lighting;
|
|
|
|
slope += shadowed;
|
|
|
|
if(slope > max_slope) {{
|
|
|
|
shadow += hardness * (1.0 - pos);
|
|
|
|
}}
|
|
|
|
max_slope = max(max_slope, slope);
|
|
|
|
pos += step;
|
|
|
|
}}
|
|
|
|
return clamp(1.0 - shadow * inv_sample_count, 0.0, 1.0);
|
|
|
|
}}
|
|
|
|
)");
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
2020-08-16 23:31:00 -04:00
|
|
|
if(use_ibl) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(vec3 ibl(const int probe, const ComputedSurfaceInfo surface_info, const float intensity) {{
|
|
|
|
const vec3 F = fresnel_schlick_roughness(surface_info.NdotV, surface_info.F0, surface_info.roughness);
|
|
|
|
const vec3 R = get_reflect(probe, surface_info.N);
|
2022-03-10 10:21:03 -05:00
|
|
|
const vec2 brdf = texture(brdfSampler, vec2(surface_info.NdotV, surface_info.roughness)).rg;
|
|
|
|
const vec3 sampledIrradiance = texture(irrandianceSampler, vec4(surface_info.N, probe)).xyz;
|
|
|
|
const vec3 prefilteredColor = textureLod(prefilterSampler, vec4(R, probe), surface_info.roughness * 4).xyz;
|
2022-02-21 13:20:55 -05:00
|
|
|
const vec3 diffuse = sampledIrradiance * surface_info.diffuse_color;
|
|
|
|
const vec3 specular = prefilteredColor * (F * brdf.x + brdf.y);
|
|
|
|
return (diffuse + specular) * intensity;
|
|
|
|
}}
|
|
|
|
)");
|
2020-08-16 23:31:00 -04:00
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
|
|
|
format_to(std::back_inserter(src), "void main() {{\n");
|
2022-02-03 10:00:59 -05:00
|
|
|
|
|
|
|
if(material.colorProperty.type == DataType::Vector3) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), "vec3 Color = vec3({}, {}, {});\n", material.colorProperty.value.x, material.colorProperty.value.y, material.colorProperty.value.z);
|
2022-02-03 10:00:59 -05:00
|
|
|
} else if(material.colorProperty.type == DataType::AssetTexture) {
|
2022-03-10 10:21:03 -05:00
|
|
|
format_to(std::back_inserter(src), "vec3 Color = texture(colorTexture, in_uv).rgb;\n");
|
2022-02-03 10:00:59 -05:00
|
|
|
} else if(material.colorProperty.type == DataType::Float) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),"vec3 Color = vec3({}});\n", material.colorProperty.float_value);
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
2022-02-03 10:00:59 -05:00
|
|
|
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(vec3 final_diffuse_color = from_srgb_to_linear(Color);
|
|
|
|
float final_roughness = scene.materials[inMaterialIndex].info.y;
|
|
|
|
float final_metallic = scene.materials[inMaterialIndex].info.x;
|
|
|
|
)");
|
2022-02-15 09:02:42 -05:00
|
|
|
|
|
|
|
if(material.normalProperty.type == DataType::AssetTexture) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
2022-03-10 10:21:03 -05:00
|
|
|
R"(vec3 final_normal = texture(normalTexture, in_uv).rgb;
|
2022-02-21 13:20:55 -05:00
|
|
|
final_normal = final_normal * 2.0 - 1.0;
|
|
|
|
final_normal = in_tbn * final_normal;
|
|
|
|
)");
|
2022-02-15 09:02:42 -05:00
|
|
|
} else {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), "vec3 final_normal = in_normal;\n");
|
2022-02-15 09:02:42 -05:00
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(ComputedSurfaceInfo surface_info = compute_surface(final_diffuse_color.rgb, final_normal, final_metallic, final_roughness);
|
|
|
|
vec3 Lo = vec3(0);
|
|
|
|
for(int i = 0; i < scene.numLights; i++) {{
|
|
|
|
const int type = int(scene.lights[i].positionType.w);
|
|
|
|
ComputedLightInformation light_info;
|
|
|
|
switch(type) {{
|
|
|
|
case 0:
|
|
|
|
light_info = calculate_point(scene.lights[i]);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
light_info = calculate_spot(scene.lights[i]);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
light_info = calculate_sun(scene.lights[i]);
|
|
|
|
break;
|
|
|
|
}}
|
|
|
|
SurfaceBRDF surface_brdf = brdf(light_info.direction, surface_info);
|
|
|
|
)");
|
2022-02-15 09:02:42 -05:00
|
|
|
|
|
|
|
if(render_options.enable_normal_mapping && material.normalProperty.type == DataType::AssetTexture && render_options.enable_normal_shadowing) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), "light_info.radiance *= calculate_normal_lighting(normalTexture, final_normal, light_info.direction);\n");
|
2022-02-15 09:02:42 -05:00
|
|
|
}
|
|
|
|
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), "Lo += ((surface_brdf.specular + surface_brdf.diffuse) * light_info.radiance * surface_brdf.NdotL) * scene.lights[i].colorSize.rgb;\n \
|
|
|
|
}}\n");
|
|
|
|
|
2020-08-11 12:07:21 -04:00
|
|
|
if(use_ibl) {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src),
|
|
|
|
R"(vec3 ambient = vec3(0.0);
|
|
|
|
float sum = 0.0;
|
2022-03-10 10:21:09 -05:00
|
|
|
for(int i = 0; i < max_probes; i++) {{
|
2022-02-21 13:20:55 -05:00
|
|
|
if(scene.probes[i].position.w == 1) {{
|
|
|
|
const vec3 position = scene.probes[i].position.xyz;
|
|
|
|
const vec3 probe_min = position - (scene.probes[i].size.xyz / 2.0);
|
|
|
|
const vec3 probe_max = position + (scene.probes[i].size.xyz / 2.0);
|
|
|
|
if(all(greaterThan(in_frag_pos, probe_min)) && all(lessThan(in_frag_pos, probe_max))) {{
|
|
|
|
float intensity = 1.0 - length(abs(in_frag_pos - position) / (scene.probes[i].size.xyz / 2.0));
|
|
|
|
intensity = clamp(intensity, 0.0, 1.0) * scene.probes[i].size.w;
|
|
|
|
ambient += ibl(i, surface_info, intensity);
|
|
|
|
sum += intensity;
|
|
|
|
}}
|
|
|
|
}} else if(scene.probes[i].position.w == 2) {{
|
|
|
|
ambient += ibl(i, surface_info, scene.probes[i].size.w);
|
|
|
|
sum += scene.probes[i].size.w;
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
ambient /= sum;
|
|
|
|
)");
|
|
|
|
|
|
|
|
format_to(std::back_inserter(src), "frag_output = vec4(ambient + Lo, 1.0);\n");
|
2020-08-11 12:07:21 -04:00
|
|
|
} else {
|
2022-02-21 13:20:55 -05:00
|
|
|
format_to(std::back_inserter(src), "frag_output = vec4(Lo, 1.0);\n");
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|
2022-02-21 13:20:55 -05:00
|
|
|
|
|
|
|
format_to(std::back_inserter(src), "}}\n");
|
|
|
|
|
|
|
|
return *shader_compiler.compile(ShaderLanguage::GLSL, ShaderStage::Fragment, ShaderSource(to_string(src)), engine->get_gfx()->accepted_shader_language());
|
2020-08-11 12:07:21 -04:00
|
|
|
}
|