feat: post-effects array parameters & add gfx.posteffects.set_array & make shadows opacity depending on clouds opacity
This commit is contained in:
parent
02a91e0b72
commit
436a89b066
@ -1,3 +1,25 @@
|
|||||||
|
local function configure_SSAO()
|
||||||
|
local slot = gfx.posteffects.index("core:default")
|
||||||
|
gfx.posteffects.set_effect(slot, "ssao")
|
||||||
|
gfx.posteffects.set_intensity(slot, 1.0)
|
||||||
|
|
||||||
|
-- Generating random SSAO samples
|
||||||
|
local buffer = Bytearray(0)
|
||||||
|
for i = 0, 63 do
|
||||||
|
local x = math.random() * 2.0 - 1.0
|
||||||
|
local y = math.random() * 2.0 - 1.0
|
||||||
|
local z = math.random()
|
||||||
|
local len = math.sqrt(x * x + y * y + z * z)
|
||||||
|
if len > 0 then
|
||||||
|
x = x / len
|
||||||
|
y = y / len
|
||||||
|
z = z / len
|
||||||
|
end
|
||||||
|
Bytearray.append(buffer, byteutil.pack("fff", x, y, z))
|
||||||
|
end
|
||||||
|
gfx.posteffects.set_array(slot, "u_ssaoSamples", Bytearray_as_string(buffer))
|
||||||
|
end
|
||||||
|
|
||||||
function on_hud_open()
|
function on_hud_open()
|
||||||
input.add_callback("player.pick", function ()
|
input.add_callback("player.pick", function ()
|
||||||
if hud.is_paused() or hud.is_inventory_open() then
|
if hud.is_paused() or hud.is_inventory_open() then
|
||||||
@ -55,8 +77,4 @@ function on_hud_open()
|
|||||||
player.set_vel(pid, 0, 1, 0)
|
player.set_vel(pid, 0, 1, 0)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local slot = gfx.posteffects.index("core:default")
|
|
||||||
gfx.posteffects.set_effect(slot, "ssao")
|
|
||||||
gfx.posteffects.set_intensity(slot, 1.0)
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
uniform vec3 u_ssaoSamples[64];
|
#param vec3 u_ssaoSamples[64]
|
||||||
|
#param int u_kernelSize = 16
|
||||||
int kernelSize = 16;
|
#param float u_radius = 0.25
|
||||||
float radius = 0.25;
|
#param float u_bias = 0.025
|
||||||
float bias = 0.025;
|
|
||||||
|
|
||||||
vec4 effect() {
|
vec4 effect() {
|
||||||
vec2 noiseScale = u_screenSize / 4.0;
|
vec2 noiseScale = u_screenSize / 4.0;
|
||||||
@ -17,9 +16,9 @@ vec4 effect() {
|
|||||||
mat3 tbn = mat3(tangent, bitangent, normal);
|
mat3 tbn = mat3(tangent, bitangent, normal);
|
||||||
|
|
||||||
float occlusion = 0.0;
|
float occlusion = 0.0;
|
||||||
for (int i = 0; i < kernelSize; i++) {
|
for (int i = 0; i < u_kernelSize; i++) {
|
||||||
vec3 samplePos = tbn * u_ssaoSamples[i];
|
vec3 samplePos = tbn * u_ssaoSamples[i];
|
||||||
samplePos = position + samplePos * radius;
|
samplePos = position + samplePos * u_radius;
|
||||||
|
|
||||||
vec4 offset = vec4(samplePos, 1.0);
|
vec4 offset = vec4(samplePos, 1.0);
|
||||||
offset = u_projection * offset;
|
offset = u_projection * offset;
|
||||||
@ -27,10 +26,10 @@ vec4 effect() {
|
|||||||
offset.xyz = offset.xyz * 0.5 + 0.5;
|
offset.xyz = offset.xyz * 0.5 + 0.5;
|
||||||
|
|
||||||
float sampleDepth = texture(u_position, offset.xy).z;
|
float sampleDepth = texture(u_position, offset.xy).z;
|
||||||
float rangeCheck = smoothstep(0.0, 1.0, radius / abs(position.z - sampleDepth));
|
float rangeCheck = smoothstep(0.0, 1.0, u_radius / abs(position.z - sampleDepth));
|
||||||
occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck;
|
occlusion += (sampleDepth >= samplePos.z + u_bias ? 1.0 : 0.0) * rangeCheck;
|
||||||
}
|
}
|
||||||
occlusion = min(1.0, 1.05 - (occlusion / kernelSize));
|
occlusion = min(1.0, 1.05 - (occlusion / u_kernelSize));
|
||||||
|
|
||||||
float z = -position.z * 0.02;
|
float z = -position.z * 0.02;
|
||||||
z = max(0.0, 1.0 - z);
|
z = max(0.0, 1.0 - z);
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
#ifndef SHADOWS_GLSL_
|
#ifndef SHADOWS_GLSL_
|
||||||
#define SHADOWS_GLSL_
|
#define SHADOWS_GLSL_
|
||||||
|
|
||||||
|
#include <constants>
|
||||||
|
|
||||||
uniform sampler2DShadow u_shadows[2];
|
uniform sampler2DShadow u_shadows[2];
|
||||||
uniform mat4 u_shadowsMatrix[2];
|
uniform mat4 u_shadowsMatrix[2];
|
||||||
uniform float u_dayTime;
|
uniform float u_dayTime;
|
||||||
uniform int u_shadowsRes;
|
uniform int u_shadowsRes;
|
||||||
|
uniform float u_shadowsOpacity;
|
||||||
|
uniform float u_shadowsSoftness;
|
||||||
|
|
||||||
float calc_shadow() {
|
float calc_shadow() {
|
||||||
if (!u_enableShadows) {
|
if (!u_enableShadows) {
|
||||||
@ -12,24 +16,25 @@ float calc_shadow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float step = 1.0 / float(u_shadowsRes);
|
float step = 1.0 / float(u_shadowsRes);
|
||||||
float s = pow(abs(cos(u_dayTime * 6.283185)), 0.5); // 2*PI precomputed
|
float s = pow(abs(cos(u_dayTime * PI2)), 0.25) * u_shadowsOpacity;
|
||||||
vec3 normalOffset = a_realnormal * (a_distance > 128.0 ? 0.2 : 0.04);
|
vec3 normalOffset = a_realnormal * (a_distance > 64.0 ? 0.2 : 0.04);
|
||||||
int shadowIdx = a_distance > 128.0 ? 1 : 0;
|
int shadowIdx = a_distance > 64.0 ? 1 : 0;
|
||||||
|
|
||||||
vec4 mpos = u_shadowsMatrix[shadowIdx] * vec4(a_modelpos.xyz + normalOffset, 1.0);
|
vec4 mpos = u_shadowsMatrix[shadowIdx] * vec4(a_modelpos.xyz + normalOffset, 1.0);
|
||||||
vec3 projCoords = mpos.xyz / mpos.w;
|
vec3 projCoords = mpos.xyz / mpos.w;
|
||||||
projCoords = projCoords * 0.5 + 0.5;
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
projCoords.z -= 0.0001;
|
projCoords.z -= 0.00001;
|
||||||
|
|
||||||
float shadow = 0.0;
|
float shadow = 0.0;
|
||||||
if (dot(a_realnormal, u_sunDir) < 0.0) {
|
if (dot(a_realnormal, u_sunDir) < 0.0) {
|
||||||
for (int y = -1; y <= 1; y++) {
|
// 5x5 kernel
|
||||||
for (int x = -1; x <= 1; x++) {
|
for (int y = -2; y <= 2; y++) {
|
||||||
vec3 offset = vec3(x, y, -(abs(x) + abs(y))) * step;
|
for (int x = -2; x <= 2; x++) {
|
||||||
|
vec3 offset = vec3(x, y, -(abs(x) + abs(y)) * 0.1) * step * 2.0 * u_shadowsSoftness;
|
||||||
shadow += texture(u_shadows[shadowIdx], projCoords + offset);
|
shadow += texture(u_shadows[shadowIdx], projCoords + offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shadow /= 9.0;
|
shadow /= 25.0;
|
||||||
} else {
|
} else {
|
||||||
shadow = 0.5;
|
shadow = 0.5;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,6 +98,8 @@ inline void source_line(std::stringstream& ss, uint linenum) {
|
|||||||
|
|
||||||
static Value default_value_for(Type type) {
|
static Value default_value_for(Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case Type::INT:
|
||||||
|
return 0;
|
||||||
case Type::FLOAT:
|
case Type::FLOAT:
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
case Type::VEC2:
|
case Type::VEC2:
|
||||||
@ -183,6 +185,8 @@ public:
|
|||||||
|
|
||||||
Value parseDefaultValue(Type type, const std::string& name) {
|
Value parseDefaultValue(Type type, const std::string& name) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case Type::INT:
|
||||||
|
return static_cast<int>(parseNumber(1).asInteger());
|
||||||
case Type::FLOAT:
|
case Type::FLOAT:
|
||||||
return static_cast<float>(parseNumber(1).asNumber());
|
return static_cast<float>(parseNumber(1).asNumber());
|
||||||
case Type::VEC2:
|
case Type::VEC2:
|
||||||
@ -212,8 +216,22 @@ public:
|
|||||||
if (params.find(paramName) != params.end()) {
|
if (params.find(paramName) != params.end()) {
|
||||||
throw error("duplicating param " + util::quote(paramName));
|
throw error("duplicating param " + util::quote(paramName));
|
||||||
}
|
}
|
||||||
|
|
||||||
skipWhitespace(false);
|
skipWhitespace(false);
|
||||||
ss << "uniform " << typeName << " " << paramName << ";\n";
|
int start = pos;
|
||||||
|
|
||||||
|
ss << "uniform " << typeName << " " << paramName;
|
||||||
|
|
||||||
|
bool array = false;
|
||||||
|
if (peekNoJump() == '[') {
|
||||||
|
skip(1);
|
||||||
|
array = true;
|
||||||
|
readUntil(']');
|
||||||
|
skip(1);
|
||||||
|
ss << source.substr(start, pos - start + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << ";\n";
|
||||||
|
|
||||||
auto defValue = default_value_for(type);
|
auto defValue = default_value_for(type);
|
||||||
// Parse default value
|
// Parse default value
|
||||||
@ -225,7 +243,7 @@ public:
|
|||||||
|
|
||||||
skipLine();
|
skipLine();
|
||||||
|
|
||||||
params[paramName] = PostEffect::Param(type, std::move(defValue));
|
params[paramName] = PostEffect::Param(type, std::move(defValue), array);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
#include "Shader.hpp"
|
#include "Shader.hpp"
|
||||||
#include "data/dv_util.hpp"
|
#include "data/dv_util.hpp"
|
||||||
|
#include "debug/Logger.hpp"
|
||||||
|
|
||||||
|
static debug::Logger logger("post-effect");
|
||||||
|
|
||||||
PostEffect::Param::Param() : type(Type::FLOAT) {}
|
PostEffect::Param::Param() : type(Type::FLOAT) {}
|
||||||
|
|
||||||
PostEffect::Param::Param(Type type, Value defValue)
|
PostEffect::Param::Param(Type type, Value defValue, bool array)
|
||||||
: type(type), defValue(defValue), value(defValue) {
|
: type(type), defValue(defValue), value(defValue), array(array) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PostEffect::PostEffect(
|
PostEffect::PostEffect(
|
||||||
@ -24,21 +27,53 @@ Shader& PostEffect::use() {
|
|||||||
if (!param.dirty) {
|
if (!param.dirty) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (param.type) {
|
if (param.array) {
|
||||||
case Param::Type::FLOAT:
|
const auto& found = arrayValues.find(name);
|
||||||
shader->uniform1f(name, std::get<float>(param.value));
|
if (found == arrayValues.end()) {
|
||||||
break;
|
continue;
|
||||||
case Param::Type::VEC2:
|
}
|
||||||
shader->uniform2f(name, std::get<glm::vec2>(param.value));
|
size_t size = found->second.size();
|
||||||
break;
|
auto ibuffer = reinterpret_cast<const int*>(found->second.data());
|
||||||
case Param::Type::VEC3:
|
auto fbuffer = reinterpret_cast<const float*>(found->second.data());
|
||||||
shader->uniform3f(name, std::get<glm::vec3>(param.value));
|
switch (param.type) {
|
||||||
break;
|
case Param::Type::INT:
|
||||||
case Param::Type::VEC4:
|
shader->uniform1v(name, size / sizeof(int), ibuffer);
|
||||||
shader->uniform4f(name, std::get<glm::vec4>(param.value));
|
break;
|
||||||
break;
|
case Param::Type::FLOAT:
|
||||||
default:
|
shader->uniform1v(name, size / sizeof(float), fbuffer);
|
||||||
assert(false);
|
break;
|
||||||
|
case Param::Type::VEC2:
|
||||||
|
shader->uniform2v(name, size / sizeof(glm::vec2), fbuffer);
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC3:
|
||||||
|
shader->uniform3v(name, size / sizeof(glm::vec3), fbuffer);
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC4:
|
||||||
|
shader->uniform4v(name, size / sizeof(glm::vec4), fbuffer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (param.type) {
|
||||||
|
case Param::Type::INT:
|
||||||
|
shader->uniform1i(name, std::get<int>(param.value));
|
||||||
|
break;
|
||||||
|
case Param::Type::FLOAT:
|
||||||
|
shader->uniform1f(name, std::get<float>(param.value));
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC2:
|
||||||
|
shader->uniform2f(name, std::get<glm::vec2>(param.value));
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC3:
|
||||||
|
shader->uniform3f(name, std::get<glm::vec3>(param.value));
|
||||||
|
break;
|
||||||
|
case Param::Type::VEC4:
|
||||||
|
shader->uniform4f(name, std::get<glm::vec4>(param.value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
param.dirty = false;
|
param.dirty = false;
|
||||||
}
|
}
|
||||||
@ -67,6 +102,9 @@ void PostEffect::setParam(const std::string& name, const dv::value& value) {
|
|||||||
}
|
}
|
||||||
auto& param = found->second;
|
auto& param = found->second;
|
||||||
switch (param.type) {
|
switch (param.type) {
|
||||||
|
case Param::Type::INT:
|
||||||
|
param.value = static_cast<int>(value.asInteger());
|
||||||
|
break;
|
||||||
case Param::Type::FLOAT:
|
case Param::Type::FLOAT:
|
||||||
param.value = static_cast<float>(value.asNumber());
|
param.value = static_cast<float>(value.asNumber());
|
||||||
break;
|
break;
|
||||||
@ -82,3 +120,20 @@ void PostEffect::setParam(const std::string& name, const dv::value& value) {
|
|||||||
}
|
}
|
||||||
param.dirty = true;
|
param.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PostEffect::setArray(const std::string& name, std::vector<ubyte>&& values) {
|
||||||
|
const auto& found = params.find(name);
|
||||||
|
if (found == params.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& param = found->second;
|
||||||
|
if (!param.array) {
|
||||||
|
logger.warning() << "set_array is used on non-array effect parameter";
|
||||||
|
if (!values.empty()) {
|
||||||
|
setParam(name, values[0]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
param.dirty = true;
|
||||||
|
arrayValues[name] = std::move(values);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "typedefs.hpp"
|
||||||
#include "data/dv_fwd.hpp"
|
#include "data/dv_fwd.hpp"
|
||||||
#include "util/EnumMetadata.hpp"
|
#include "util/EnumMetadata.hpp"
|
||||||
|
|
||||||
@ -14,24 +16,26 @@ class Shader;
|
|||||||
class PostEffect {
|
class PostEffect {
|
||||||
public:
|
public:
|
||||||
struct Param {
|
struct Param {
|
||||||
enum class Type { FLOAT, VEC2, VEC3, VEC4 };
|
enum class Type { INT, FLOAT, VEC2, VEC3, VEC4 };
|
||||||
|
|
||||||
VC_ENUM_METADATA(Type)
|
VC_ENUM_METADATA(Type)
|
||||||
|
{"int", Type::INT},
|
||||||
{"float", Type::FLOAT},
|
{"float", Type::FLOAT},
|
||||||
{"vec2", Type::VEC2},
|
{"vec2", Type::VEC2},
|
||||||
{"vec3", Type::VEC3},
|
{"vec3", Type::VEC3},
|
||||||
{"vec4", Type::VEC4},
|
{"vec4", Type::VEC4},
|
||||||
VC_ENUM_END
|
VC_ENUM_END
|
||||||
|
|
||||||
using Value = std::variant<float, glm::vec2, glm::vec3, glm::vec4>;
|
using Value = std::variant<int, float, glm::vec2, glm::vec3, glm::vec4>;
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
Value defValue;
|
Value defValue;
|
||||||
Value value;
|
Value value;
|
||||||
|
bool array = false;
|
||||||
bool dirty = true;
|
bool dirty = true;
|
||||||
|
|
||||||
Param();
|
Param();
|
||||||
Param(Type type, Value defValue);
|
Param(Type type, Value defValue, bool array);
|
||||||
};
|
};
|
||||||
|
|
||||||
PostEffect(
|
PostEffect(
|
||||||
@ -49,6 +53,8 @@ public:
|
|||||||
|
|
||||||
void setParam(const std::string& name, const dv::value& value);
|
void setParam(const std::string& name, const dv::value& value);
|
||||||
|
|
||||||
|
void setArray(const std::string& name, std::vector<ubyte>&& values);
|
||||||
|
|
||||||
bool isAdvanced() const {
|
bool isAdvanced() const {
|
||||||
return advanced;
|
return advanced;
|
||||||
}
|
}
|
||||||
@ -60,5 +66,6 @@ private:
|
|||||||
bool advanced = false;
|
bool advanced = false;
|
||||||
std::shared_ptr<Shader> shader;
|
std::shared_ptr<Shader> shader;
|
||||||
std::unordered_map<std::string, Param> params;
|
std::unordered_map<std::string, Param> params;
|
||||||
|
std::unordered_map<std::string, std::vector<ubyte>> arrayValues;
|
||||||
float intensity = 0.0f;
|
float intensity = 0.0f;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -43,20 +43,6 @@ PostProcessing::PostProcessing(size_t effectSlotsCount)
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
std::uniform_real_distribution<float> randomFloats(0.0, 1.0);
|
|
||||||
std::default_random_engine generator;
|
|
||||||
for (unsigned int i = 0; i < 64; ++i)
|
|
||||||
{
|
|
||||||
glm::vec3 sample(
|
|
||||||
randomFloats(generator) * 2.0 - 1.0,
|
|
||||||
randomFloats(generator) * 2.0 - 1.0,
|
|
||||||
randomFloats(generator)
|
|
||||||
);
|
|
||||||
sample = glm::normalize(sample);
|
|
||||||
sample *= randomFloats(generator);
|
|
||||||
ssaoKernel.push_back(sample);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PostProcessing::~PostProcessing() = default;
|
PostProcessing::~PostProcessing() = default;
|
||||||
@ -90,21 +76,13 @@ void PostProcessing::refreshFbos(uint width, uint height) {
|
|||||||
|
|
||||||
void PostProcessing::configureEffect(
|
void PostProcessing::configureEffect(
|
||||||
const DrawContext& context,
|
const DrawContext& context,
|
||||||
|
PostEffect& effect,
|
||||||
Shader& shader,
|
Shader& shader,
|
||||||
float timer,
|
float timer,
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
uint shadowMap
|
uint shadowMap
|
||||||
) {
|
) {
|
||||||
const auto& viewport = context.getViewport();
|
const auto& viewport = context.getViewport();
|
||||||
|
|
||||||
bool ssaoConfigured = false;
|
|
||||||
if (!ssaoConfigured) {
|
|
||||||
for (unsigned int i = 0; i < 64; ++i) {
|
|
||||||
auto name = "u_ssaoSamples["+ std::to_string(i) + "]";
|
|
||||||
shader.uniform3f(name, ssaoKernel[i]);
|
|
||||||
}
|
|
||||||
ssaoConfigured = true;
|
|
||||||
}
|
|
||||||
shader.uniform1i("u_screen", 0);
|
shader.uniform1i("u_screen", 0);
|
||||||
if (gbuffer) {
|
if (gbuffer) {
|
||||||
shader.uniform1i("u_position", 1);
|
shader.uniform1i("u_position", 1);
|
||||||
@ -156,7 +134,7 @@ void PostProcessing::render(
|
|||||||
if (totalPasses == 0) {
|
if (totalPasses == 0) {
|
||||||
auto& effect = assets.require<PostEffect>("default");
|
auto& effect = assets.require<PostEffect>("default");
|
||||||
auto& shader = effect.use();
|
auto& shader = effect.use();
|
||||||
configureEffect(context, shader, timer, camera, shadowMap);
|
configureEffect(context, effect, shader, timer, camera, shadowMap);
|
||||||
quadMesh->draw();
|
quadMesh->draw();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -170,7 +148,7 @@ void PostProcessing::render(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto& shader = effect->use();
|
auto& shader = effect->use();
|
||||||
configureEffect(context, shader, timer, camera, shadowMap);
|
configureEffect(context, *effect, shader, timer, camera, shadowMap);
|
||||||
|
|
||||||
if (currentPass > 1) {
|
if (currentPass > 1) {
|
||||||
fbo->getTexture()->bind();
|
fbo->getTexture()->bind();
|
||||||
|
|||||||
@ -58,6 +58,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void configureEffect(
|
void configureEffect(
|
||||||
const DrawContext& context,
|
const DrawContext& context,
|
||||||
|
PostEffect& effect,
|
||||||
Shader& shader,
|
Shader& shader,
|
||||||
float timer,
|
float timer,
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
@ -73,7 +74,5 @@ private:
|
|||||||
std::unique_ptr<Mesh<PostProcessingVertex>> quadMesh;
|
std::unique_ptr<Mesh<PostProcessingVertex>> quadMesh;
|
||||||
std::vector<std::shared_ptr<PostEffect>> effectSlots;
|
std::vector<std::shared_ptr<PostEffect>> effectSlots;
|
||||||
std::unique_ptr<GBuffer> gbuffer;
|
std::unique_ptr<GBuffer> gbuffer;
|
||||||
|
|
||||||
std::vector<glm::vec3> ssaoKernel;
|
|
||||||
uint noiseTexture;
|
uint noiseTexture;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -76,6 +76,25 @@ void Shader::uniform4f(const std::string& name, const glm::vec4& xyzw) {
|
|||||||
glUniform4f(getUniformLocation(name), xyzw.x, xyzw.y, xyzw.z, xyzw.w);
|
glUniform4f(getUniformLocation(name), xyzw.x, xyzw.y, xyzw.z, xyzw.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shader::uniform1v(const std::string& name, int length, const int* v) {
|
||||||
|
glUniform1iv(getUniformLocation(name), length, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::uniform1v(const std::string& name, int length, const float* v) {
|
||||||
|
glUniform1fv(getUniformLocation(name), length, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::uniform2v(const std::string& name, int length, const float* v) {
|
||||||
|
glUniform2fv(getUniformLocation(name), length, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::uniform3v(const std::string& name, int length, const float* v) {
|
||||||
|
glUniform3fv(getUniformLocation(name), length, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::uniform4v(const std::string& name, int length, const float* v) {
|
||||||
|
glUniform4fv(getUniformLocation(name), length, v);
|
||||||
|
}
|
||||||
|
|
||||||
inline auto shader_deleter = [](GLuint* shader) {
|
inline auto shader_deleter = [](GLuint* shader) {
|
||||||
glDeleteShader(*shader);
|
glDeleteShader(*shader);
|
||||||
|
|||||||
@ -32,6 +32,12 @@ public:
|
|||||||
void uniform3f(const std::string& name, const glm::vec3& xyz);
|
void uniform3f(const std::string& name, const glm::vec3& xyz);
|
||||||
void uniform4f(const std::string& name, const glm::vec4& xyzw);
|
void uniform4f(const std::string& name, const glm::vec4& xyzw);
|
||||||
|
|
||||||
|
void uniform1v(const std::string& name, int length, const int* v);
|
||||||
|
void uniform1v(const std::string& name, int length, const float* v);
|
||||||
|
void uniform2v(const std::string& name, int length, const float* v);
|
||||||
|
void uniform3v(const std::string& name, int length, const float* v);
|
||||||
|
void uniform4v(const std::string& name, int length, const float* v);
|
||||||
|
|
||||||
/// @brief Create shader program using vertex and fragment shaders source.
|
/// @brief Create shader program using vertex and fragment shaders source.
|
||||||
/// @param vertexFile vertex shader file name
|
/// @param vertexFile vertex shader file name
|
||||||
/// @param fragmentFile fragment shader file name
|
/// @param fragmentFile fragment shader file name
|
||||||
|
|||||||
@ -131,10 +131,14 @@ void WorldRenderer::setupWorldShader(
|
|||||||
shader.uniform1i("u_enableShadows", shadows);
|
shader.uniform1i("u_enableShadows", shadows);
|
||||||
|
|
||||||
if (shadows) {
|
if (shadows) {
|
||||||
|
const auto& worldInfo = level.getWorld()->getInfo();
|
||||||
|
float cloudsIntensity = glm::max(worldInfo.fog, weather.clouds());
|
||||||
shader.uniformMatrix("u_shadowsMatrix[0]", shadowCamera.getProjView());
|
shader.uniformMatrix("u_shadowsMatrix[0]", shadowCamera.getProjView());
|
||||||
shader.uniformMatrix("u_shadowsMatrix[1]", wideShadowCamera.getProjView());
|
shader.uniformMatrix("u_shadowsMatrix[1]", wideShadowCamera.getProjView());
|
||||||
shader.uniform3f("u_sunDir", shadowCamera.front);
|
shader.uniform3f("u_sunDir", shadowCamera.front);
|
||||||
shader.uniform1i("u_shadowsRes", shadowMap->getResolution());
|
shader.uniform1i("u_shadowsRes", shadowMap->getResolution());
|
||||||
|
shader.uniform1f("u_shadowsOpacity", 1.0f - cloudsIntensity); // TODO: make it configurable
|
||||||
|
shader.uniform1f("u_shadowsSoftness", 1.0f + cloudsIntensity * 4); // TODO: make it configurable
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE4);
|
glActiveTexture(GL_TEXTURE4);
|
||||||
shader.uniform1i("u_shadows[0]", 4);
|
shader.uniform1i("u_shadows[0]", 4);
|
||||||
@ -359,7 +363,7 @@ void WorldRenderer::generateShadowsMap(
|
|||||||
const auto& settings = engine.getSettings();
|
const auto& settings = engine.getSettings();
|
||||||
int resolution = shadowMap.getResolution();
|
int resolution = shadowMap.getResolution();
|
||||||
float shadowMapScale =
|
float shadowMapScale =
|
||||||
0.2f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) *
|
0.16f / (1 << glm::max(0L, settings.graphics.shadowsQuality.get())) *
|
||||||
scale;
|
scale;
|
||||||
float shadowMapSize = resolution * shadowMapScale;
|
float shadowMapSize = resolution * shadowMapScale;
|
||||||
|
|
||||||
@ -383,9 +387,9 @@ void WorldRenderer::generateShadowsMap(
|
|||||||
);
|
);
|
||||||
shadowCamera.updateVectors();
|
shadowCamera.updateVectors();
|
||||||
|
|
||||||
shadowCamera.position -= shadowCamera.front * 300.0f;
|
shadowCamera.position -= shadowCamera.front * 500.0f;
|
||||||
shadowCamera.position += shadowCamera.up * 10.0f;
|
shadowCamera.position += shadowCamera.up * 0.0f;
|
||||||
shadowCamera.position += camera.front * 100.0f;
|
shadowCamera.position += camera.front * 0.0f;
|
||||||
|
|
||||||
auto view = shadowCamera.getView();
|
auto view = shadowCamera.getView();
|
||||||
|
|
||||||
@ -445,9 +449,7 @@ void WorldRenderer::draw(
|
|||||||
|
|
||||||
const auto& worldInfo = world->getInfo();
|
const auto& worldInfo = world->getInfo();
|
||||||
|
|
||||||
float sqrtT = glm::sqrt(weather.t);
|
float clouds = weather.clouds();
|
||||||
float clouds = weather.b.clouds * sqrtT +
|
|
||||||
weather.a.clouds * (1.0f - sqrtT);
|
|
||||||
clouds = glm::max(worldInfo.fog, clouds);
|
clouds = glm::max(worldInfo.fog, clouds);
|
||||||
float mie = 1.0f + glm::max(worldInfo.fog, clouds * 0.5f) * 2.0f;
|
float mie = 1.0f + glm::max(worldInfo.fog, clouds * 0.5f) * 2.0f;
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,22 @@ static int l_set_params(lua::State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_set_array(lua::State* L) {
|
||||||
|
size_t index = static_cast<size_t>(lua::tointeger(L, 1));
|
||||||
|
auto key = lua::require_string(L, 2);
|
||||||
|
auto data = lua::require_lstring(L, 3);
|
||||||
|
auto effect = post_processing->getEffect(index);
|
||||||
|
if (effect == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::vector<ubyte> buffer(
|
||||||
|
reinterpret_cast<const ubyte*>(data.begin()),
|
||||||
|
reinterpret_cast<const ubyte*>(data.end())
|
||||||
|
);
|
||||||
|
effect->setArray(key, std::move(buffer));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const luaL_Reg posteffectslib[] = {
|
const luaL_Reg posteffectslib[] = {
|
||||||
{"index", lua::wrap<l_index>},
|
{"index", lua::wrap<l_index>},
|
||||||
{"set_effect", lua::wrap<l_set_effect>},
|
{"set_effect", lua::wrap<l_set_effect>},
|
||||||
@ -64,5 +80,6 @@ const luaL_Reg posteffectslib[] = {
|
|||||||
{"set_intensity", lua::wrap<l_set_intensity>},
|
{"set_intensity", lua::wrap<l_set_intensity>},
|
||||||
{"is_active", lua::wrap<l_is_active>},
|
{"is_active", lua::wrap<l_is_active>},
|
||||||
{"set_params", lua::wrap<l_set_params>},
|
{"set_params", lua::wrap<l_set_params>},
|
||||||
|
{"set_array", lua::wrap<l_set_array>},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#include "libs/api_lua.hpp"
|
#include "libs/api_lua.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
@ -149,6 +150,15 @@ int l_debug_print(lua::State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::normal_distribution<double> randomFloats(0.0f, 1.0f);
|
||||||
|
std::default_random_engine generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_math_normal_random(lua::State* L) {
|
||||||
|
return lua::pushnumber(L, randomFloats(generator));
|
||||||
|
}
|
||||||
|
|
||||||
void initialize_libs_extends(lua::State* L) {
|
void initialize_libs_extends(lua::State* L) {
|
||||||
if (lua::getglobal(L, "debug")) {
|
if (lua::getglobal(L, "debug")) {
|
||||||
lua::pushcfunction(L, lua::wrap<l_debug_error>);
|
lua::pushcfunction(L, lua::wrap<l_debug_error>);
|
||||||
@ -163,6 +173,12 @@ void initialize_libs_extends(lua::State* L) {
|
|||||||
lua::pushcfunction(L, lua::wrap<l_debug_print>);
|
lua::pushcfunction(L, lua::wrap<l_debug_print>);
|
||||||
lua::setfield(L, "print");
|
lua::setfield(L, "print");
|
||||||
|
|
||||||
|
lua::pop(L);
|
||||||
|
}
|
||||||
|
if (lua::getglobal(L, "math")) {
|
||||||
|
lua::pushcfunction(L, lua::wrap<l_math_normal_random>);
|
||||||
|
lua::setfield(L, "normal_random");
|
||||||
|
|
||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "presets/WeatherPreset.hpp"
|
#include "presets/WeatherPreset.hpp"
|
||||||
@ -45,6 +46,11 @@ struct Weather : Serializable {
|
|||||||
return b.thunderRate * t + a.thunderRate * (1.0f - t);
|
return b.thunderRate * t + a.thunderRate * (1.0f - t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float clouds() const {
|
||||||
|
float sqrtT = glm::sqrt(t);
|
||||||
|
return b.clouds * sqrtT + a.clouds * (1.0f - sqrtT);
|
||||||
|
}
|
||||||
|
|
||||||
dv::value serialize() const override;
|
dv::value serialize() const override;
|
||||||
void deserialize(const dv::value& src) override;
|
void deserialize(const dv::value& src) override;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user