|
|
@ -32,6 +32,7 @@ |
|
|
|
#include "rasterizer/texture-filter.hpp"
|
|
|
|
#include "renderer/vertex-attributes.hpp"
|
|
|
|
#include "renderer/render-context.hpp"
|
|
|
|
#include "renderer/model.hpp"
|
|
|
|
#include "scene/camera.hpp"
|
|
|
|
#include "scene/scene.hpp"
|
|
|
|
#include "scene/ambient-light.hpp"
|
|
|
@ -45,11 +46,15 @@ sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, r |
|
|
|
render_pass(rasterizer, framebuffer), |
|
|
|
mouse_position({0.0f, 0.0f}), |
|
|
|
sun_light(nullptr), |
|
|
|
time_of_day(0.0f) |
|
|
|
moon_light(nullptr), |
|
|
|
time_of_day(0.0f), |
|
|
|
sky_model(nullptr), |
|
|
|
sky_model_vao(nullptr) |
|
|
|
{ |
|
|
|
shader_program = resource_manager->load<::shader_program>("sky.glsl"); |
|
|
|
matrix_input = shader_program->get_input("matrix"); |
|
|
|
model_view_projection_input = shader_program->get_input("model_view_projection"); |
|
|
|
sun_direction_input = shader_program->get_input("sun_direction"); |
|
|
|
moon_direction_input = shader_program->get_input("moon_direction"); |
|
|
|
sun_angular_radius_input = shader_program->get_input("sun_angular_radius"); |
|
|
|
sun_angular_radius_input = shader_program->get_input("sun_angular_radius"); |
|
|
|
sun_color_input = shader_program->get_input("sun_color"); |
|
|
@ -91,38 +96,54 @@ sky_pass::~sky_pass() |
|
|
|
|
|
|
|
void sky_pass::render(render_context* context) const |
|
|
|
{ |
|
|
|
if (!sky_model_vao) |
|
|
|
return; |
|
|
|
|
|
|
|
rasterizer->use_framebuffer(*framebuffer); |
|
|
|
|
|
|
|
glDisable(GL_BLEND); |
|
|
|
glDisable(GL_DEPTH_TEST); |
|
|
|
glDepthMask(GL_FALSE); |
|
|
|
glDisable(GL_CULL_FACE); |
|
|
|
glEnable(GL_CULL_FACE); |
|
|
|
glCullFace(GL_BACK); |
|
|
|
|
|
|
|
auto viewport = framebuffer->get_dimensions(); |
|
|
|
rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport)); |
|
|
|
|
|
|
|
float time = (time_tween) ? time_tween->interpolate(context->alpha) : 0.0f; |
|
|
|
float2 resolution = {static_cast<float>(std::get<0>(viewport)), static_cast<float>(std::get<1>(viewport))}; |
|
|
|
float3 sun_direction = {0, -1, 0}; |
|
|
|
|
|
|
|
float3 sun_direction = {0, -1, 0}; |
|
|
|
if (sun_light) |
|
|
|
{ |
|
|
|
sun_direction = sun_light->get_direction_tween().interpolate(context->alpha); |
|
|
|
} |
|
|
|
|
|
|
|
// Calculate matrix
|
|
|
|
float4x4 model_view = math::resize<4, 4>(math::resize<3, 3>(context->camera->get_view_tween().interpolate(context->alpha))); |
|
|
|
float4x4 inverse_projection = math::inverse(context->camera->get_projection_tween().interpolate(context->alpha)); |
|
|
|
float4x4 matrix = math::inverse(model_view) * inverse_projection; |
|
|
|
|
|
|
|
float3 moon_direction = {0, -1, 0}; |
|
|
|
if (moon_light) |
|
|
|
{ |
|
|
|
moon_direction = moon_light->get_direction_tween().interpolate(context->alpha); |
|
|
|
} |
|
|
|
|
|
|
|
const ::camera& camera = *context->camera; |
|
|
|
float clip_near = camera.get_clip_near_tween().interpolate(context->alpha); |
|
|
|
float clip_far = camera.get_clip_far_tween().interpolate(context->alpha); |
|
|
|
float3 model_scale = float3{1.0f, 1.0f, 1.0f} * (clip_near + clip_far) * 0.5f; |
|
|
|
float4x4 model = math::scale(math::identity4x4<float>, model_scale); |
|
|
|
float4x4 model_view = math::resize<4, 4>(math::resize<3, 3>(camera.get_view_tween().interpolate(context->alpha))) * model; |
|
|
|
float4x4 projection = camera.get_projection_tween().interpolate(context->alpha); |
|
|
|
float4x4 model_view_projection = projection * model_view; |
|
|
|
|
|
|
|
// Change shader program
|
|
|
|
rasterizer->use_program(*shader_program); |
|
|
|
|
|
|
|
// Upload shader parameters
|
|
|
|
if (matrix_input) |
|
|
|
matrix_input->upload(matrix); |
|
|
|
if (model_view_projection_input) |
|
|
|
model_view_projection_input->upload(model_view_projection); |
|
|
|
if (sun_direction_input) |
|
|
|
sun_direction_input->upload(sun_direction); |
|
|
|
if (moon_direction_input) |
|
|
|
moon_direction_input->upload(moon_direction); |
|
|
|
if (sun_angular_radius_input) |
|
|
|
sun_angular_radius_input->upload(sun_angular_radius); |
|
|
|
if (sun_color_input) |
|
|
@ -138,8 +159,30 @@ void sky_pass::render(render_context* context) const |
|
|
|
if (time_of_day_input) |
|
|
|
time_of_day_input->upload(time_of_day); |
|
|
|
|
|
|
|
// Draw quad
|
|
|
|
rasterizer->draw_arrays(*quad_vao, drawing_mode::triangles, 0, 6); |
|
|
|
// Draw sky model
|
|
|
|
rasterizer->draw_arrays(*sky_model_vao, sky_model_drawing_mode, sky_model_start_index, sky_model_index_count); |
|
|
|
} |
|
|
|
|
|
|
|
void sky_pass::set_sky_model(const model* model) |
|
|
|
{ |
|
|
|
sky_model = model; |
|
|
|
|
|
|
|
if (sky_model) |
|
|
|
{ |
|
|
|
sky_model_vao = model->get_vertex_array(); |
|
|
|
|
|
|
|
const std::vector<model_group*>& groups = *model->get_groups(); |
|
|
|
for (model_group* group: groups) |
|
|
|
{ |
|
|
|
sky_model_drawing_mode = group->get_drawing_mode(); |
|
|
|
sky_model_start_index = group->get_start_index(); |
|
|
|
sky_model_index_count = group->get_index_count(); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
sky_model_vao = nullptr; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void sky_pass::set_sun_angular_radius(float angle) |
|
|
@ -157,6 +200,11 @@ void sky_pass::set_sun_light(const directional_light* light) |
|
|
|
sun_light = light; |
|
|
|
} |
|
|
|
|
|
|
|
void sky_pass::set_moon_light(const directional_light* light) |
|
|
|
{ |
|
|
|
moon_light = light; |
|
|
|
} |
|
|
|
|
|
|
|
void sky_pass::set_sky_gradient(const std::array<float4, 4>& gradient) |
|
|
|
{ |
|
|
|
sky_gradient = gradient; |
|
|
|