mirror of
https://github.com/luanti-org/luanti.git
synced 2025-11-21 17:05:20 +01:00
Support array textures in shadow renderer (the lazy way)
This commit is contained in:
@@ -1,18 +1,22 @@
|
|||||||
// FIXME missing array texture handling
|
#ifdef USE_ARRAY_TEXTURE
|
||||||
uniform sampler2D ColorMapSampler;
|
uniform mediump sampler2DArray baseTexture;
|
||||||
|
#else
|
||||||
|
uniform sampler2D baseTexture;
|
||||||
|
#endif
|
||||||
varying vec4 tPos;
|
varying vec4 tPos;
|
||||||
|
|
||||||
#ifdef GL_ES
|
CENTROID_ VARYING_ mediump vec2 varTexCoord;
|
||||||
varying mediump vec2 varTexCoord;
|
CENTROID_ VARYING_ float varTexLayer; // actually int
|
||||||
#else
|
|
||||||
centroid varying vec2 varTexCoord;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 col = texture2D(ColorMapSampler, varTexCoord);
|
#ifdef USE_ARRAY_TEXTURE
|
||||||
// FIXME: magic number???
|
vec4 base = texture(baseTexture, vec3(varTexCoord, varTexLayer)).rgba;
|
||||||
if (col.a < 0.70)
|
#else
|
||||||
|
vec4 base = texture2D(baseTexture, varTexCoord).rgba;
|
||||||
|
#endif
|
||||||
|
// (this totally ignores the node's alpha mode)
|
||||||
|
if (base.a < 0.70)
|
||||||
discard;
|
discard;
|
||||||
|
|
||||||
float depth = 0.5 + tPos.z * 0.5;
|
float depth = 0.5 + tPos.z * 0.5;
|
||||||
|
|||||||
@@ -6,11 +6,8 @@ uniform float xyPerspectiveBias0;
|
|||||||
uniform float xyPerspectiveBias1;
|
uniform float xyPerspectiveBias1;
|
||||||
uniform float zPerspectiveBias;
|
uniform float zPerspectiveBias;
|
||||||
|
|
||||||
#ifdef GL_ES
|
CENTROID_ VARYING_ mediump vec2 varTexCoord;
|
||||||
varying mediump vec2 varTexCoord;
|
CENTROID_ VARYING_ float varTexLayer; // actually int
|
||||||
#else
|
|
||||||
centroid varying vec2 varTexCoord;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec4 getRelativePosition(in vec4 position)
|
vec4 getRelativePosition(in vec4 position)
|
||||||
{
|
{
|
||||||
@@ -45,5 +42,9 @@ void main()
|
|||||||
tPos = applyPerspectiveDistortion(pos);
|
tPos = applyPerspectiveDistortion(pos);
|
||||||
|
|
||||||
gl_Position = vec4(tPos.xyz, 1.0);
|
gl_Position = vec4(tPos.xyz, 1.0);
|
||||||
varTexCoord = (mTexture * vec4(inTexCoord0.xy, 0.0, 1.0)).xy;
|
|
||||||
|
varTexCoord = (mTexture * vec4(inTexCoord0.xy, 1.0, 1.0)).st;
|
||||||
|
#ifdef USE_ARRAY_TEXTURE
|
||||||
|
varTexLayer = inVertexAux;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
// FIXME missing array texture handling
|
#ifdef USE_ARRAY_TEXTURE
|
||||||
uniform sampler2D ColorMapSampler;
|
uniform mediump sampler2DArray baseTexture;
|
||||||
|
#else
|
||||||
|
uniform sampler2D baseTexture;
|
||||||
|
#endif
|
||||||
varying vec4 tPos;
|
varying vec4 tPos;
|
||||||
|
|
||||||
#ifdef GL_ES
|
CENTROID_ VARYING_ mediump vec2 varTexCoord;
|
||||||
varying mediump vec2 varTexCoord;
|
CENTROID_ VARYING_ float varTexLayer; // actually int
|
||||||
#else
|
|
||||||
centroid varying vec2 varTexCoord;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef COLORED_SHADOWS
|
#ifdef COLORED_SHADOWS
|
||||||
varying vec3 varColor;
|
varying vec3 varColor;
|
||||||
@@ -21,27 +21,27 @@ float packColor(vec3 color)
|
|||||||
+ floor(color.g * c_precision + 0.5) * c_precisionp1
|
+ floor(color.g * c_precision + 0.5) * c_precisionp1
|
||||||
+ floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
|
+ floor(color.r * c_precision + 0.5) * c_precisionp1 * c_precisionp1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vec3 black = vec3(0.0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 col = texture2D(ColorMapSampler, varTexCoord);
|
#ifdef USE_ARRAY_TEXTURE
|
||||||
|
vec4 base = texture(baseTexture, vec3(varTexCoord, varTexLayer)).rgba;
|
||||||
|
#else
|
||||||
|
vec4 base = texture2D(baseTexture, varTexCoord).rgba;
|
||||||
|
#endif
|
||||||
#ifndef COLORED_SHADOWS
|
#ifndef COLORED_SHADOWS
|
||||||
if (col.a < 0.5)
|
if (base.a < 0.5)
|
||||||
discard;
|
discard;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float depth = 0.5 + tPos.z * 0.5;
|
float depth = 0.5 + tPos.z * 0.5;
|
||||||
// ToDo: Liso: Apply movement on waving plants
|
|
||||||
// depth in [0, 1] for texture
|
// depth in [0, 1] for texture
|
||||||
|
|
||||||
//col.rgb = col.a == 1.0 ? vec3(1.0) : col.rgb;
|
|
||||||
#ifdef COLORED_SHADOWS
|
#ifdef COLORED_SHADOWS
|
||||||
col.rgb *= varColor.rgb;
|
base.rgb *= varColor.rgb;
|
||||||
// premultiply color alpha (see-through side)
|
// premultiply color alpha (see-through side)
|
||||||
float packedColor = packColor(col.rgb * (1.0 - col.a));
|
float packedColor = packColor(base.rgb * (1.0 - base.a));
|
||||||
gl_FragColor = vec4(depth, packedColor, 0.0,1.0);
|
gl_FragColor = vec4(depth, packedColor, 0.0,1.0);
|
||||||
#else
|
#else
|
||||||
gl_FragColor = vec4(depth, 0.0, 0.0, 1.0);
|
gl_FragColor = vec4(depth, 0.0, 0.0, 1.0);
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ uniform float xyPerspectiveBias0;
|
|||||||
uniform float xyPerspectiveBias1;
|
uniform float xyPerspectiveBias1;
|
||||||
uniform float zPerspectiveBias;
|
uniform float zPerspectiveBias;
|
||||||
|
|
||||||
#ifdef GL_ES
|
CENTROID_ VARYING_ mediump vec2 varTexCoord;
|
||||||
varying mediump vec2 varTexCoord;
|
CENTROID_ VARYING_ float varTexLayer; // actually int
|
||||||
#else
|
|
||||||
centroid varying vec2 varTexCoord;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec4 getRelativePosition(in vec4 position)
|
vec4 getRelativePosition(in vec4 position)
|
||||||
{
|
{
|
||||||
@@ -48,7 +45,11 @@ void main()
|
|||||||
tPos = applyPerspectiveDistortion(pos);
|
tPos = applyPerspectiveDistortion(pos);
|
||||||
|
|
||||||
gl_Position = vec4(tPos.xyz, 1.0);
|
gl_Position = vec4(tPos.xyz, 1.0);
|
||||||
varTexCoord = inTexCoord0.xy;
|
|
||||||
|
varTexCoord = (mTexture * vec4(inTexCoord0.xy, 1.0, 1.0)).st;
|
||||||
|
#ifdef USE_ARRAY_TEXTURE
|
||||||
|
varTexLayer = inVertexAux;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef COLORED_SHADOWS
|
#ifdef COLORED_SHADOWS
|
||||||
varColor = inVertexColor.rgb;
|
varColor = inVertexColor.rgb;
|
||||||
|
|||||||
@@ -192,9 +192,6 @@ static size_t getArrayTextureMax(IShaderSource *shdsrc)
|
|||||||
// must support sampling from them
|
// must support sampling from them
|
||||||
if (!shdsrc->supportsSampler2DArray())
|
if (!shdsrc->supportsSampler2DArray())
|
||||||
return 0;
|
return 0;
|
||||||
// shadow shaders can't handle array textures yet (TODO)
|
|
||||||
if (g_settings->getBool("enable_dynamic_shadows"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
u32 n = driver->getLimits().MaxArrayTextureImages;
|
u32 n = driver->getLimits().MaxArrayTextureImages;
|
||||||
constexpr u32 type_max = std::numeric_limits<decltype(TileLayer::texture_layer_idx)>::max();
|
constexpr u32 type_max = std::numeric_limits<decltype(TileLayer::texture_layer_idx)>::max();
|
||||||
|
|||||||
@@ -49,13 +49,16 @@ ShadowRenderer::~ShadowRenderer()
|
|||||||
// call to disable releases dynamically allocated resources
|
// call to disable releases dynamically allocated resources
|
||||||
disable();
|
disable();
|
||||||
|
|
||||||
if (m_shadow_depth_cb) {
|
for (auto *ptr : m_shadow_depth_cb) {
|
||||||
m_shadow_depth_cb->drop();
|
if (ptr)
|
||||||
m_shadow_depth_cb = nullptr;
|
ptr->drop();
|
||||||
}
|
}
|
||||||
if (m_shadow_depth_trans_cb) {
|
m_shadow_depth_cb.clear();
|
||||||
m_shadow_depth_trans_cb->drop();
|
|
||||||
m_shadow_depth_trans_cb = nullptr;
|
auto *gpu = m_driver->getGPUProgrammingServices();
|
||||||
|
for (auto id : {depth_shader, depth_shader_a, depth_shader_trans, depth_shader_trans_a}) {
|
||||||
|
if (id != video::EMT_INVALID)
|
||||||
|
gpu->deleteShaderMaterial(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete m_screen_quad;
|
delete m_screen_quad;
|
||||||
@@ -231,14 +234,14 @@ void ShadowRenderer::updateSMTextures()
|
|||||||
video::ECOLOR_FORMAT frt;
|
video::ECOLOR_FORMAT frt;
|
||||||
if (m_shadow_map_texture_32bit) {
|
if (m_shadow_map_texture_32bit) {
|
||||||
if (m_shadow_map_colored)
|
if (m_shadow_map_colored)
|
||||||
frt = video::ECOLOR_FORMAT::ECF_A32B32G32R32F;
|
frt = video::ECF_A32B32G32R32F;
|
||||||
else
|
else
|
||||||
frt = video::ECOLOR_FORMAT::ECF_R32F;
|
frt = video::ECF_R32F;
|
||||||
} else {
|
} else {
|
||||||
if (m_shadow_map_colored)
|
if (m_shadow_map_colored)
|
||||||
frt = video::ECOLOR_FORMAT::ECF_A16B16G16R16F;
|
frt = video::ECF_A16B16G16R16F;
|
||||||
else
|
else
|
||||||
frt = video::ECOLOR_FORMAT::ECF_R16F;
|
frt = video::ECF_R16F;
|
||||||
}
|
}
|
||||||
shadowMapTextureFinal = getSMTexture(
|
shadowMapTextureFinal = getSMTexture(
|
||||||
std::string("shadowmap_final_") + itos(m_shadow_map_texture_size),
|
std::string("shadowmap_final_") + itos(m_shadow_map_texture_size),
|
||||||
@@ -271,7 +274,7 @@ void ShadowRenderer::updateSMTextures()
|
|||||||
// Update SM incrementally:
|
// Update SM incrementally:
|
||||||
for (DirectionalLight &light : m_light_list) {
|
for (DirectionalLight &light : m_light_list) {
|
||||||
// Static shader values.
|
// Static shader values.
|
||||||
for (auto *cb : {m_shadow_depth_cb, m_shadow_depth_trans_cb}) {
|
for (auto *cb : m_shadow_depth_cb) {
|
||||||
if (cb) {
|
if (cb) {
|
||||||
cb->MapRes = (u32)m_shadow_map_texture_size;
|
cb->MapRes = (u32)m_shadow_map_texture_size;
|
||||||
cb->MaxFar = (f32)m_shadow_map_max_distance * BS;
|
cb->MaxFar = (f32)m_shadow_map_max_distance * BS;
|
||||||
@@ -292,7 +295,6 @@ void ShadowRenderer::updateSMTextures()
|
|||||||
// This is also handled in ClientMap.
|
// This is also handled in ClientMap.
|
||||||
if (m_current_frame == m_map_shadow_update_frames - 1 || m_force_update_shadow_map) {
|
if (m_current_frame == m_map_shadow_update_frames - 1 || m_force_update_shadow_map) {
|
||||||
if (m_shadow_map_colored) {
|
if (m_shadow_map_colored) {
|
||||||
m_driver->setRenderTarget(0, false, false);
|
|
||||||
m_driver->setRenderTarget(shadowMapTextureColors,
|
m_driver->setRenderTarget(shadowMapTextureColors,
|
||||||
true, false, video::SColor(255, 255, 255, 255));
|
true, false, video::SColor(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
@@ -340,7 +342,10 @@ void ShadowRenderer::update(video::ITexture *outputTarget)
|
|||||||
// Static shader values for entities are set in updateSMTextures
|
// Static shader values for entities are set in updateSMTextures
|
||||||
// SM texture for entities is not updated incrementally and
|
// SM texture for entities is not updated incrementally and
|
||||||
// must by updated using current player position.
|
// must by updated using current player position.
|
||||||
m_shadow_depth_cb->CameraPos = light.getPlayerPos();
|
for (auto *cb : m_shadow_depth_cb) {
|
||||||
|
if (cb)
|
||||||
|
cb->CameraPos = light.getPlayerPos();
|
||||||
|
}
|
||||||
|
|
||||||
// render shadows for the non-map objects.
|
// render shadows for the non-map objects.
|
||||||
m_driver->setRenderTarget(shadowMapTextureDynamicObjects, true,
|
m_driver->setRenderTarget(shadowMapTextureDynamicObjects, true,
|
||||||
@@ -435,10 +440,19 @@ void ShadowRenderer::renderShadowMap(video::ITexture *target,
|
|||||||
mat.FrontfaceCulling = false;
|
mat.FrontfaceCulling = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we unconditionally replace the material shader with our custom ones
|
||||||
|
* to render the depth map.
|
||||||
|
* Be warned that this is a very flawed approach and the reason why waving
|
||||||
|
* doesn't work or why the node alpha mode is totally ignored.
|
||||||
|
* Array texture support was tacked on but this should really be rewritten:
|
||||||
|
* The shadow map code should be part of nodes_shader and activated on demand.
|
||||||
|
*/
|
||||||
|
bool array_tex = mat.getTexture(0) && mat.getTexture(0)->getType() == video::ETT_2D_ARRAY;
|
||||||
if (m_shadow_map_colored && is_transparent_pass) {
|
if (m_shadow_map_colored && is_transparent_pass) {
|
||||||
mat.MaterialType = depth_shader_trans;
|
mat.MaterialType = array_tex ? depth_shader_trans_a : depth_shader_trans;
|
||||||
} else {
|
} else {
|
||||||
mat.MaterialType = depth_shader;
|
mat.MaterialType = array_tex ? depth_shader_a : depth_shader;
|
||||||
mat.BlendOperation = video::EBO_MIN;
|
mat.BlendOperation = video::EBO_MIN;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -478,6 +492,8 @@ void ShadowRenderer::renderShadowObjects(
|
|||||||
auto ¤t_mat = shadow_node.node->getMaterial(m);
|
auto ¤t_mat = shadow_node.node->getMaterial(m);
|
||||||
|
|
||||||
BufferMaterialList.push_back(current_mat.MaterialType);
|
BufferMaterialList.push_back(current_mat.MaterialType);
|
||||||
|
// Note: this suffers from the same misdesign and will break once we
|
||||||
|
// start doing more special shader things for entities.
|
||||||
current_mat.MaterialType = depth_shader;
|
current_mat.MaterialType = depth_shader;
|
||||||
|
|
||||||
BufferMaterialCullingList.emplace_back(
|
BufferMaterialCullingList.emplace_back(
|
||||||
@@ -517,22 +533,43 @@ void ShadowRenderer::createShaders()
|
|||||||
{
|
{
|
||||||
auto *shdsrc = m_client->getShaderSource();
|
auto *shdsrc = m_client->getShaderSource();
|
||||||
|
|
||||||
assert(!m_shadow_depth_cb);
|
assert(m_shadow_depth_cb.empty());
|
||||||
|
|
||||||
|
ShaderConstants a_const;
|
||||||
|
a_const["USE_ARRAY_TEXTURE"] = 1;
|
||||||
|
|
||||||
{
|
{
|
||||||
m_shadow_depth_cb = new ShadowDepthUniformSetter();
|
auto *cb = new ShadowDepthUniformSetter();
|
||||||
|
m_shadow_depth_cb.push_back(cb);
|
||||||
u32 shader_id = shdsrc->getShader("shadow/pass1", {},
|
u32 shader_id = shdsrc->getShader("shadow/pass1", {},
|
||||||
video::EMT_SOLID, m_shadow_depth_cb);
|
video::EMT_SOLID, cb);
|
||||||
depth_shader = shdsrc->getShaderInfo(shader_id).material;
|
depth_shader = shdsrc->getShaderInfo(shader_id).material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shdsrc->supportsSampler2DArray()) {
|
||||||
|
auto *cb = new ShadowDepthUniformSetter();
|
||||||
|
m_shadow_depth_cb.push_back(cb);
|
||||||
|
u32 shader_id = shdsrc->getShader("shadow/pass1", a_const,
|
||||||
|
video::EMT_SOLID, cb);
|
||||||
|
depth_shader_a = shdsrc->getShaderInfo(shader_id).material;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_shadow_map_colored) {
|
if (m_shadow_map_colored) {
|
||||||
m_shadow_depth_trans_cb = new ShadowDepthUniformSetter();
|
auto *cb = new ShadowDepthUniformSetter();
|
||||||
|
m_shadow_depth_cb.push_back(cb);
|
||||||
u32 shader_id = shdsrc->getShader("shadow/pass1_trans", {},
|
u32 shader_id = shdsrc->getShader("shadow/pass1_trans", {},
|
||||||
video::EMT_SOLID, m_shadow_depth_trans_cb);
|
video::EMT_SOLID, cb);
|
||||||
depth_shader_trans = shdsrc->getShaderInfo(shader_id).material;
|
depth_shader_trans = shdsrc->getShaderInfo(shader_id).material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_shadow_map_colored && shdsrc->supportsSampler2DArray()) {
|
||||||
|
auto *cb = new ShadowDepthUniformSetter();
|
||||||
|
m_shadow_depth_cb.push_back(cb);
|
||||||
|
u32 shader_id = shdsrc->getShader("shadow/pass1_trans", a_const,
|
||||||
|
video::EMT_SOLID, cb);
|
||||||
|
depth_shader_trans_a = shdsrc->getShaderInfo(shader_id).material;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto *shadow_mix_cb = new ShadowScreenQuadUniformSetter();
|
auto *shadow_mix_cb = new ShadowScreenQuadUniformSetter();
|
||||||
u32 shader_id = shdsrc->getShader("shadow/pass2", {},
|
u32 shader_id = shdsrc->getShader("shadow/pass2", {},
|
||||||
|
|||||||
@@ -138,17 +138,20 @@ private:
|
|||||||
f32 m_perspective_bias_xy;
|
f32 m_perspective_bias_xy;
|
||||||
f32 m_perspective_bias_z;
|
f32 m_perspective_bias_z;
|
||||||
|
|
||||||
video::ECOLOR_FORMAT m_texture_format{video::ECOLOR_FORMAT::ECF_R16F};
|
video::ECOLOR_FORMAT m_texture_format{video::ECF_R16F};
|
||||||
video::ECOLOR_FORMAT m_texture_format_color{video::ECOLOR_FORMAT::ECF_R16G16};
|
video::ECOLOR_FORMAT m_texture_format_color{video::ECF_R16G16};
|
||||||
|
|
||||||
// Shadow Shader stuff
|
// Shadow Shader stuff
|
||||||
|
|
||||||
void createShaders();
|
void createShaders();
|
||||||
|
|
||||||
video::E_MATERIAL_TYPE depth_shader, depth_shader_trans;
|
// _a suffix is with support for array textures
|
||||||
|
video::E_MATERIAL_TYPE depth_shader{video::EMT_INVALID},
|
||||||
|
depth_shader_a{video::EMT_INVALID};
|
||||||
|
video::E_MATERIAL_TYPE depth_shader_trans{video::EMT_INVALID},
|
||||||
|
depth_shader_trans_a{video::EMT_INVALID};
|
||||||
|
|
||||||
ShadowDepthUniformSetter *m_shadow_depth_cb{nullptr};
|
std::vector<ShadowDepthUniformSetter*> m_shadow_depth_cb;
|
||||||
ShadowDepthUniformSetter *m_shadow_depth_trans_cb{nullptr};
|
|
||||||
|
|
||||||
ShadowScreenQuad *m_screen_quad{nullptr};
|
ShadowScreenQuad *m_screen_quad{nullptr};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user