mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-09 08:00:04 +01:00
Add gfx.antialiasing (off, msaax2/x4/x8, taa) with temporal anti-aliasing in the GL 4.6 and Vulkan renderers
This commit is contained in:
@@ -1640,7 +1640,7 @@ bool scene_walk::Render(TDynamicObject *Dynamic)
|
||||
glm::mat4 future_stack = model_ubs.future;
|
||||
|
||||
glm::mat4 mv = OpenGLMatrices.data(GL_MODELVIEW);
|
||||
model_ubs.future *= glm::translate(mv, glm::vec3(Dynamic->get_future_movement())) * glm::inverse(mv);
|
||||
model_ubs.future *= glm::translate(mv, glm::vec3(m_motionhistory ? -Dynamic->get_future_movement() : Dynamic->get_future_movement())) * glm::inverse(mv);
|
||||
// the velocity it leaves in the colour pass keeps the motion blur on (Render_pass())
|
||||
if ((m_renderpass.draw_mode == rendermode::color) && (Dynamic->get_future_movement() != glm::dvec3{0.0}))
|
||||
m_vehiclesmoving = true;
|
||||
@@ -1901,7 +1901,7 @@ void scene_walk::Render(TSubModel *Submodel)
|
||||
Submodel->RaAnimation(Submodel->b_aAnim);
|
||||
|
||||
glm::mat4 mv = OpenGLMatrices.data(GL_MODELVIEW);
|
||||
model_ubs.future *= (mv * Submodel->future_transform) * glm::inverse(mv);
|
||||
model_ubs.future *= (mv * (m_motionhistory ? glm::inverse(Submodel->future_transform) : Submodel->future_transform)) * glm::inverse(mv);
|
||||
// the placement may be different in the next frame: the walk isn't kept (Record_Indirect_Draws())
|
||||
m_indirectchanging = true;
|
||||
}
|
||||
@@ -2716,7 +2716,7 @@ bool scene_walk::Render_Alpha(TDynamicObject *Dynamic)
|
||||
glm::mat4 future_stack = model_ubs.future;
|
||||
|
||||
glm::mat4 mv = OpenGLMatrices.data(GL_MODELVIEW);
|
||||
model_ubs.future *= glm::translate(mv, glm::vec3(Dynamic->get_future_movement())) * glm::inverse(mv);
|
||||
model_ubs.future *= glm::translate(mv, glm::vec3(m_motionhistory ? -Dynamic->get_future_movement() : Dynamic->get_future_movement())) * glm::inverse(mv);
|
||||
// the velocity it leaves in the colour pass keeps the motion blur on (Render_pass())
|
||||
if ((m_renderpass.draw_mode == rendermode::color) && (Dynamic->get_future_movement() != glm::dvec3{0.0}))
|
||||
m_vehiclesmoving = true;
|
||||
@@ -2846,7 +2846,7 @@ void scene_walk::Render_Alpha(TSubModel *Submodel)
|
||||
Submodel->RaAnimation(Submodel->b_aAnim);
|
||||
|
||||
glm::mat4 mv = OpenGLMatrices.data(GL_MODELVIEW);
|
||||
model_ubs.future *= (mv * Submodel->future_transform) * glm::inverse(mv);
|
||||
model_ubs.future *= (mv * (m_motionhistory ? glm::inverse(Submodel->future_transform) : Submodel->future_transform)) * glm::inverse(mv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -502,6 +502,12 @@ class scene_walk
|
||||
std::vector<gl::instance_draw_command> m_indirectcommandsordered;
|
||||
// a vehicle drawn in the colour pass of this frame moved (motion blur)
|
||||
bool m_vehiclesmoving{false};
|
||||
// the velocities point to the last frame (the temporal anti-aliasing, gfx::temporal_aa) instead of the next one (the motion
|
||||
// blur alone): the moving vehicles and the turning wheels add their motion to the future of the draws backwards
|
||||
bool m_motionhistory{false};
|
||||
// the future of the draws of the cab and the interiors of its vehicle: the identity (they move with the camera), or the matrix
|
||||
// of their view of the last frame (gfx::temporal_aa::cab_future())
|
||||
glm::mat4 m_cabfuture{1.f};
|
||||
// set while a preview is drawn: submodels faded out entirely are skipped, instead of being drawn invisible over the stencil
|
||||
bool m_previewing{false};
|
||||
// the last lighting of the pass placed the cab lamp among the lights: the cab is lit by it, not by an addition to the ambient light
|
||||
|
||||
89
rendering/common/temporalaa.cpp
Normal file
89
rendering/common/temporalaa.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "rendering/common/temporalaa.h"
|
||||
|
||||
#include "vehicle/DynObj.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// the offsets go round this many frames: enough to cover a pixel evenly, few enough for the history to hold all of them
|
||||
constexpr std::uint32_t JITTER_PHASES{8};
|
||||
// the camera moved farther than this from one frame to the next (another camera, another vehicle, a jump): the history is dropped
|
||||
constexpr double CAMERA_JUMP{50.0};
|
||||
|
||||
// the halton sequence: the index written in the base, mirrored behind the point
|
||||
float halton(std::uint32_t Index, std::uint32_t const Base)
|
||||
{
|
||||
auto fraction{1.f};
|
||||
auto result{0.f};
|
||||
while (Index > 0)
|
||||
{
|
||||
fraction /= static_cast<float>(Base);
|
||||
result += fraction * static_cast<float>(Index % Base);
|
||||
Index /= Base;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
glm::mat4 gfx::temporal_aa::begin_frame(glm::mat4 const &Projection, glm::dmat3 const &View, glm::dvec3 const &Camera, TDynamicObject const *Cab, glm::ivec2 const &Size)
|
||||
{
|
||||
m_phase = (m_phase + 1) % JITTER_PHASES;
|
||||
// the first element of the sequence is 0 in every base; from the second one on they are spread over the pixel
|
||||
m_jitter = glm::vec2{halton(m_phase + 1, 2), halton(m_phase + 1, 3)} - 0.5f;
|
||||
glm::dvec2 const size{static_cast<double>(std::max(Size.x, 1)), static_cast<double>(std::max(Size.y, 1))};
|
||||
// the clip space is two units across the image
|
||||
auto const offset{glm::translate(glm::dmat4{1.0}, glm::dvec3{2.0 * glm::dvec2{m_jitter} / size, 0.0})};
|
||||
|
||||
frame current;
|
||||
current.projection = glm::dmat4{Projection};
|
||||
current.view = View;
|
||||
current.camera = Camera;
|
||||
current.vehicle = Cab;
|
||||
if (Cab != nullptr)
|
||||
{
|
||||
// as Render_cab() places it
|
||||
current.cab = glm::translate(glm::dmat4{1.0}, Cab->GetPosition() - Camera) * Cab->mMatrix;
|
||||
}
|
||||
current.size = Size;
|
||||
current.valid = true;
|
||||
|
||||
auto const projection{offset * current.projection};
|
||||
m_historyvalid = m_previous.valid && (m_previous.size == Size) && (m_previous.vehicle == Cab) && (glm::length(Camera - m_previous.camera) < CAMERA_JUMP);
|
||||
if (m_historyvalid)
|
||||
{
|
||||
auto const inverseprojection{glm::inverse(projection)};
|
||||
// the view of this frame to the world around the camera, the world around the camera of the last frame, its view
|
||||
auto const toworld{glm::dmat4{glm::inverse(current.view)}};
|
||||
auto const world{glm::dmat4{m_previous.view} * glm::translate(glm::dmat4{1.0}, Camera - m_previous.camera) * toworld};
|
||||
// the cab goes with its vehicle: the view of this frame to the cab, to the world around the camera of the last frame
|
||||
auto const cab{glm::dmat4{m_previous.view} * m_previous.cab * glm::inverse(current.cab) * toworld};
|
||||
// the shaders project the future with the projection of this frame (the velocity is the place in the future less the place
|
||||
// now, both with the offset of this frame): the projection of the last frame with the offset of this one is put in front of
|
||||
// it in the future. with the projection the same in both frames this is the identity, and the velocity holds just the motion
|
||||
auto const previous{offset * m_previous.projection};
|
||||
auto const projectionfix{inverseprojection * previous};
|
||||
m_worldfuture = glm::mat4{projectionfix * world};
|
||||
m_cabfuture = glm::mat4{projectionfix * cab};
|
||||
m_reprojection = glm::mat4{previous * world * inverseprojection};
|
||||
}
|
||||
else
|
||||
{
|
||||
m_worldfuture = glm::mat4{1.f};
|
||||
m_cabfuture = glm::mat4{1.f};
|
||||
m_reprojection = glm::mat4{1.f};
|
||||
}
|
||||
m_target = 1 - m_target;
|
||||
m_previous = current;
|
||||
return glm::mat4{projection};
|
||||
}
|
||||
94
rendering/common/temporalaa.h
Normal file
94
rendering/common/temporalaa.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// the temporal anti-aliasing of the main view (gfx.antialiasing taa), the part shared by the renderers: the sub-pixel offset of the
|
||||
// projection of every frame, and the matrices which take the pixels of a frame to the place they had in the last one.
|
||||
//
|
||||
// with it the velocities of the colour pass point to the last frame: the future of the draws (model_ubs.future) is the matrix of the
|
||||
// view of the last frame instead of the next one, for the scenery and for the cab apart (the cab moves with the camera), and the
|
||||
// moving vehicles and wheels take their motion backwards (scene_walk::m_motionhistory). the resolve pass (postfx_taa.frag,
|
||||
// taa_resolve.glsl) reads the history with the velocities, and takes the pixels of the world standing still (and the sky, which has
|
||||
// no velocity drawn) to the last frame with reprojection(); on those the thin things (rails, wires) are kept in the history for a few
|
||||
// frames although the pixel of this frame misses them
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class TDynamicObject;
|
||||
|
||||
namespace gfx
|
||||
{
|
||||
|
||||
class temporal_aa
|
||||
{
|
||||
public:
|
||||
// the frame of the colour pass of the main view: Projection without the offset, View the rotation of the camera (the axes of the
|
||||
// world to those of the view), Camera its place, Cab the vehicle whose cab is drawn (or null), Size of the images of the pass.
|
||||
// returns the projection with the offset of the frame
|
||||
glm::mat4 begin_frame(glm::mat4 const &Projection, glm::dmat3 const &View, glm::dvec3 const &Camera, TDynamicObject const *Cab, glm::ivec2 const &Size);
|
||||
// the next frame starts the history anew
|
||||
void reset()
|
||||
{
|
||||
m_previous.valid = false;
|
||||
}
|
||||
// the frame has a history: the last frame was drawn the same way
|
||||
bool history_valid() const
|
||||
{
|
||||
return m_historyvalid;
|
||||
}
|
||||
// model_ubs.future of the scenery, and of the cab with the interiors of its vehicle
|
||||
glm::mat4 const &world_future() const
|
||||
{
|
||||
return m_worldfuture;
|
||||
}
|
||||
glm::mat4 const &cab_future() const
|
||||
{
|
||||
return m_cabfuture;
|
||||
}
|
||||
// the clip space of the pixels of this frame (with their depth) to the clip space of the last frame, for the world standing still
|
||||
glm::mat4 const &reprojection() const
|
||||
{
|
||||
return m_reprojection;
|
||||
}
|
||||
// the image of the history written this frame (0 or 1); the other one holds the last frame
|
||||
int target() const
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
// the offset of the frame, in pixels
|
||||
glm::vec2 jitter() const
|
||||
{
|
||||
return m_jitter;
|
||||
}
|
||||
|
||||
private:
|
||||
struct frame
|
||||
{
|
||||
glm::dmat4 projection{1.0}; // without the offset
|
||||
glm::dmat3 view{1.0};
|
||||
glm::dvec3 camera{0.0};
|
||||
glm::dmat4 cab{1.0}; // the cab to the world around the camera
|
||||
TDynamicObject const *vehicle{nullptr};
|
||||
glm::ivec2 size{0};
|
||||
bool valid{false};
|
||||
};
|
||||
|
||||
frame m_previous;
|
||||
std::uint32_t m_phase{0};
|
||||
glm::vec2 m_jitter{0.f};
|
||||
glm::mat4 m_worldfuture{1.f};
|
||||
glm::mat4 m_cabfuture{1.f};
|
||||
glm::mat4 m_reprojection{1.f};
|
||||
int m_target{0};
|
||||
bool m_historyvalid{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
Reference in New Issue
Block a user