1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-09-15 18:57:08 +00:00

Volumetric effects

This commit is contained in:
Gefüllte Taubenbrust 2024-07-05 12:15:22 +02:00
parent cd6e304cfa
commit 22ba7449f2
15 changed files with 468 additions and 23 deletions

View file

@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include <cmath>
// Menu clouds are created later
class Clouds;
Clouds *g_menuclouds = NULL;
@ -344,6 +343,7 @@ void Clouds::updateMesh()
void Clouds::render()
{
#if 0
if (m_params.density <= 0.0f)
return; // no need to do anything
@ -394,13 +394,7 @@ void Clouds::render()
// Restore fog settings
driver->setFog(fog_color, fog_type, fog_start, fog_end, fog_density,
fog_pixelfog, fog_rangefog);
}
void Clouds::renderVolumetrics() {
video::IVideoDriver* driver = SceneManager->getVideoDriver();
v2u32 ss = driver->getScreenSize();
core::rect<s32> rect(0, 0, ss.X, ss.Y);
driver->draw2DRectangle(video::SColor(255, 255, 255, 255), rect);
#endif
}
void Clouds::step(float dtime)

View file

@ -52,8 +52,6 @@ public:
virtual void render();
void renderVolumetrics();
virtual const aabb3f &getBoundingBox() const
{
return m_box;
@ -93,6 +91,10 @@ public:
invalidateMesh();
}
float getDensity() const {
return m_params.density;
}
void setColorBright(video::SColor color_bright)
{
m_params.color_bright = color_bright;
@ -112,6 +114,10 @@ public:
invalidateMesh();
}
float getHeight() const {
return m_params.height;
}
void setSpeed(v2f speed)
{
m_params.speed = speed;
@ -126,6 +132,10 @@ public:
invalidateMesh();
}
float getThickness() const {
return m_params.thickness;
}
bool isCameraInsideCloud() const { return m_camera_inside_cloud; }
const video::SColor getColor() const { return m_color.toSColor(); }
@ -147,7 +157,7 @@ private:
bool gridFilled(int x, int y) const;
video::SMaterial m_volume_material;
video::ITexture *m_density_texture = nullptr;
video::SMaterial m_material;
irr_ptr<scene::SMeshBuffer> m_meshbuffer;

View file

@ -383,9 +383,18 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
m_animation_timer_delta_pixel{"animationTimerDelta"};
CachedPixelShaderSetting<float, 3> m_artificial_light{ "artificialLight" };
CachedPixelShaderSetting<float, 3> m_day_light{"dayLight"};
CachedPixelShaderSetting<float, 3> m_eye_position_pixel{ "eyePosition" };
CachedVertexShaderSetting<float, 3> m_eye_position_vertex{ "eyePosition" };
CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"};
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"};
CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"};
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{"cameraPosition"};
CachedVertexShaderSetting<float, 16> m_camera_projinv_vertex{"mCameraProjInv"};
CachedPixelShaderSetting<float, 16> m_camera_projinv_pixel{"mCameraProjInv"};
CachedVertexShaderSetting<float, 16> m_camera_view_vertex{"mCameraView"};
CachedPixelShaderSetting<float, 16> m_camera_view_pixel{"mCameraView"};
CachedPixelShaderSetting<float> m_camera_near_pixel{"cameraNear"};
CachedPixelShaderSetting<float> m_camera_far_pixel{"cameraFar"};
CachedPixelShaderSetting<SamplerLayer_t> m_texture0{"texture0"};
CachedPixelShaderSetting<SamplerLayer_t> m_texture1{"texture1"};
CachedPixelShaderSetting<SamplerLayer_t> m_texture2{"texture2"};
@ -408,6 +417,9 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
float m_bloom_strength;
CachedPixelShaderSetting<float> m_bloom_radius_pixel{"bloomRadius"};
float m_bloom_radius;
CachedPixelShaderSetting<float> m_cloud_height_pixel{"cloudHeight"};
CachedPixelShaderSetting<float> m_cloud_thickness_pixel{"cloudThickness"};
CachedPixelShaderSetting<float> m_cloud_density_pixel{"cloudDensity"};
CachedPixelShaderSetting<float> m_saturation_pixel{"saturation"};
float m_gamma;
CachedPixelShaderSetting<float> m_gamma_pixel{"gamma"};
@ -489,6 +501,10 @@ public:
m_animation_timer_delta_vertex.set(&animation_timer_delta_f, services);
m_animation_timer_delta_pixel.set(&animation_timer_delta_f, services);
v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition();
m_eye_position_pixel.set(epos, services);
m_eye_position_vertex.set(epos, services);
if (m_client->getMinimap()) {
v3f minimap_yaw = m_client->getMinimap()->getYawVec();
m_minimap_yaw.set(minimap_yaw, services);
@ -498,6 +514,24 @@ public:
m_camera_offset_pixel.set(offset, services);
m_camera_offset_vertex.set(offset, services);
v3f camera_position = m_client->getCamera()->getPosition();
m_camera_position_pixel.set(camera_position, services);
core::matrix4 camera_proj = m_client->getCamera()->getCameraNode()->getProjectionMatrix();
core::matrix4 camera_projinv;
camera_proj.getInverse(camera_projinv);
m_camera_projinv_vertex.set(camera_projinv, services);
m_camera_projinv_pixel.set(camera_projinv, services);
core::matrix4 camera_view = m_client->getCamera()->getCameraNode()->getViewMatrix();
m_camera_view_vertex.set(camera_view, services);
m_camera_view_pixel.set(camera_view, services);
float camera_near = m_client->getCamera()->getCameraNode()->getNearValue();
m_camera_near_pixel.set(&camera_near, services);
float camera_far = m_client->getCamera()->getCameraNode()->getFarValue();
m_camera_far_pixel.set(&camera_far, services);
SamplerLayer_t tex_id;
tex_id = 0;
m_texture0.set(&tex_id, services);
@ -537,6 +571,17 @@ public:
video::SColorf artificial_light = lighting.artificial_light_color;
m_artificial_light.set(artificial_light, services);
// TODO: settings
Clouds* clouds = m_client->getClouds();
if (m_client->getClouds()) {
float cloud_height = clouds->getHeight() * 10.0f;
m_cloud_height_pixel.set(&cloud_height, services);
float cloud_thickness = clouds->getThickness() * 10.0f;
m_cloud_thickness_pixel.set(&cloud_thickness, services);
float cloud_density = clouds->getDensity();
m_cloud_density_pixel.set(&cloud_density, services);
}
if (m_volumetric_light_enabled) {
// Map directional light to screen space
auto camera_node = m_client->getCamera()->getCameraNode();

View file

@ -66,11 +66,6 @@ void DrawHUD::run(PipelineContext &context)
context.client->getCamera()->drawNametags();
}
context.device->getGUIEnvironment()->drawAll();
// TODO: proper settings
if (true && context.client->getClouds()) {
context.client->getClouds()->renderVolumetrics();
}
}

View file

@ -25,6 +25,65 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/tile.h"
#include "settings.h"
class NoiseStep : public RenderStep {
public:
NoiseStep(u32 shader_id, u8 texture_id) :
shader_id(shader_id), texture_id(texture_id)
{
material.UseMipMaps = false;
material.ZBuffer = true;
material.ZWriteEnable = video::EZW_ON;
}
void setRenderSource(RenderSource* _source) override {
source = _source;
}
void setRenderTarget(RenderTarget* _target) override {
target = _target;
}
void reset(PipelineContext& context) override {}
void run(PipelineContext& context) override {
video::ITexture* texture = source->getTexture(texture_id);
if (texture != last_texture) {
last_texture = texture;
if (target)
target->activate(context);
// attach the shader
material.MaterialType = context.client->getShaderSource()->getShaderInfo(shader_id).material;
auto driver = context.device->getVideoDriver();
static const video::SColor color = video::SColor(0, 0, 0, 255);
static const video::S3DVertex vertices[4] = {
video::S3DVertex(1.0, -1.0, 0.0, 0.0, 0.0, -1.0,
color, 1.0, 0.0),
video::S3DVertex(-1.0, -1.0, 0.0, 0.0, 0.0, -1.0,
color, 0.0, 0.0),
video::S3DVertex(-1.0, 1.0, 0.0, 0.0, 0.0, -1.0,
color, 0.0, 1.0),
video::S3DVertex(1.0, 1.0, 0.0, 0.0, 0.0, -1.0,
color, 1.0, 1.0),
};
static const u16 indices[6] = { 0, 1, 2, 2, 3, 0 };
driver->setMaterial(material);
driver->drawVertexPrimitiveList(&vertices, 4, &indices, 2);
}
}
private:
u32 shader_id;
u8 texture_id;
video::SMaterial material;
video::ITexture* last_texture = nullptr;
RenderSource* source{ nullptr };
RenderTarget* target{ nullptr };
};
PostProcessingStep::PostProcessingStep(u32 _shader_id, const std::vector<u8> &_texture_map) :
shader_id(_shader_id), texture_map(_texture_map)
{
@ -65,7 +124,6 @@ void PostProcessingStep::run(PipelineContext &context)
if (target)
target->activate(context);
// attach the shader
material.MaterialType = context.client->getShaderSource()->getShaderInfo(shader_id).material;
auto driver = context.device->getVideoDriver();
@ -96,6 +154,12 @@ void PostProcessingStep::setBilinearFilter(u8 index, bool value)
material.TextureLayers[index].MagFilter = value ? video::ETMAGF_LINEAR : video::ETMAGF_NEAREST;
}
void PostProcessingStep::setWrapRepeat(u8 index, bool value) {
assert(index < video::MATERIAL_MAX_TEXTURES);
material.TextureLayers[index].TextureWrapU = value ? video::ETC_REPEAT : video::ETC_CLAMP_TO_EDGE;
material.TextureLayers[index].TextureWrapV = value ? video::ETC_REPEAT : video::ETC_CLAMP_TO_EDGE;
}
RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep, v2f scale, Client *client)
{
auto buffer = pipeline->createOwned<TextureBuffer>();
@ -121,8 +185,13 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
static const u8 TEXTURE_EXPOSURE_2 = 4;
static const u8 TEXTURE_FXAA = 5;
static const u8 TEXTURE_VOLUME = 6;
static const u8 TEXTURE_SCALE_DOWN = 10;
static const u8 TEXTURE_SCALE_UP = 20;
static const u8 TEXTURE_CLOUDS_1 = 7;
static const u8 TEXTURE_CLOUDS_2 = 8;
static const u8 TEXTURE_CLOUD_DENSITY = 9;
static const u8 TEXTURE_NOISE = 10;
static const u8 TEXTURE_NOISE_COARSE = 11;
static const u8 TEXTURE_SCALE_DOWN = 20;
static const u8 TEXTURE_SCALE_UP = 30;
// Super-sampling is simply rendering into a larger texture.
// Downscaling is done by the final step when rendering to the screen.
@ -132,6 +201,8 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
const bool enable_ssaa = antialiasing == "ssaa";
const bool enable_fxaa = antialiasing == "fxaa";
const bool enable_volumetric_light = g_settings->getBool("enable_volumetric_lighting") && enable_bloom;
const bool enable_volumetric_clouds = true;
// TODO: Add clouds setting
if (enable_ssaa) {
u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa"));
@ -152,10 +223,47 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
// Number of mipmap levels of the bloom downsampling texture
const u8 MIPMAP_LEVELS = 4;
// post-processing stage
u8 source = TEXTURE_COLOR;
if (enable_volumetric_clouds) {
buffer->setTexture(TEXTURE_NOISE, core::dimension2du(256, 256), "noise", color_format);
shader_id = client->getShaderSource()->getShader("noise_shader", TILE_MATERIAL_PLAIN, NDT_MESH);
RenderStep *noise_step = pipeline->addStep<NoiseStep>(shader_id, TEXTURE_NOISE);
noise_step->setRenderSource(buffer);
noise_step->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_NOISE));
buffer->setTexture(TEXTURE_NOISE_COARSE, core::dimension2du(256, 256), "noise", color_format);
shader_id = client->getShaderSource()->getShader("coarse_noise_shader", TILE_MATERIAL_PLAIN, NDT_MESH);
noise_step = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8>());
noise_step->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_NOISE_COARSE));
buffer->setTexture(TEXTURE_CLOUDS_1, scale * 0.25f, "clouds_1", color_format, /*clear:*/ true);
buffer->setTexture(TEXTURE_CLOUDS_2, scale, "clouds_2", color_format);
buffer->setTexture(TEXTURE_CLOUD_DENSITY, scale, "cloud_density", color_format);
shader_id = client->getShaderSource()->getShader("volumetric_clouds", TILE_MATERIAL_PLAIN, NDT_MESH);
PostProcessingStep *volumetric_clouds = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_DEPTH, TEXTURE_NOISE, TEXTURE_NOISE_COARSE });
volumetric_clouds->setRenderSource(buffer);
volumetric_clouds->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_CLOUDS_1));
volumetric_clouds->setBilinearFilter(1, true);
volumetric_clouds->setBilinearFilter(2, true);
volumetric_clouds->setWrapRepeat(1, true);
volumetric_clouds->setWrapRepeat(2, true);
source = TEXTURE_CLOUDS_1;
shader_id = client->getShaderSource()->getShader("clouds_merge", TILE_MATERIAL_PLAIN, NDT_MESH);
PostProcessingStep* blend_clouds = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_CLOUDS_1, TEXTURE_COLOR });
blend_clouds->setRenderSource(buffer);
blend_clouds->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_CLOUDS_2));
blend_clouds->setBilinearFilter(0, true);
source = TEXTURE_CLOUDS_2;
}
// common downsampling step for bloom or autoexposure
if (enable_bloom || enable_auto_exposure) {
@ -173,7 +281,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
// get bright spots
u32 shader_id = client->getShaderSource()->getShader("extract_bloom", TILE_MATERIAL_PLAIN, NDT_MESH);
RenderStep *extract_bloom = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { source, TEXTURE_EXPOSURE_1 });
auto extract_bloom = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { source, TEXTURE_EXPOSURE_1 });
extract_bloom->setRenderSource(buffer);
extract_bloom->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLOOM));
source = TEXTURE_BLOOM;
@ -224,7 +332,7 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
}
// FXAA
u8 final_stage_source = TEXTURE_COLOR;
u8 final_stage_source = TEXTURE_CLOUDS_2;
if (enable_fxaa) {
final_stage_source = TEXTURE_FXAA;

View file

@ -49,6 +49,9 @@ public:
* @param value true to enable the bilinear filter, false to disable
*/
void setBilinearFilter(u8 index, bool value);
void setWrapRepeat(u8 index, bool value);
private:
u32 shader_id;
std::vector<u8> texture_map;