mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
Fixes and proper tangent space
This commit is contained in:
parent
6ad43575ff
commit
2fd22c1850
12 changed files with 417 additions and 70 deletions
|
@ -44,6 +44,8 @@ uniform vec2 windowSize;
|
|||
uniform float fov;
|
||||
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vTangent;
|
||||
varying vec3 vBinormal;
|
||||
varying vec3 vPosition;
|
||||
// World position in the visible world (i.e. relative to the cameraOffset.)
|
||||
// This can be used for many shader effects without loss of precision.
|
||||
|
@ -100,36 +102,6 @@ vec3 gnoise(vec3 p){
|
|||
);
|
||||
}
|
||||
|
||||
float snoise(vec3 p)
|
||||
{
|
||||
vec3 a = floor(p);
|
||||
vec3 d = p - a;
|
||||
d = d * d * (3.0 - 2.0 * d);
|
||||
|
||||
vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);
|
||||
vec4 k1 = perm(b.xyxy);
|
||||
vec4 k2 = perm(k1.xyxy + b.zzww);
|
||||
|
||||
vec4 c = k2 + a.zzzz;
|
||||
vec4 k3 = perm(c);
|
||||
vec4 k4 = perm(c + 1.0);
|
||||
|
||||
vec4 o1 = fract(k3 * (1.0 / 41.0));
|
||||
vec4 o2 = fract(k4 * (1.0 / 41.0));
|
||||
|
||||
vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);
|
||||
vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);
|
||||
|
||||
return o4.y * d.y + o4.x * (1.0 - d.y);
|
||||
}
|
||||
|
||||
vec3 hnoise(vec3 p) {
|
||||
vec3 g = gnoise(p);
|
||||
float s = snoise(p);
|
||||
g *= 3.0 / (1.0 + exp(-16.0 * (s - 0.5))) - 1.5;
|
||||
return g;
|
||||
}
|
||||
|
||||
vec2 wave_noise(vec3 p, float off) {
|
||||
return (gnoise(p + vec3(0.0, 0.0, off)) * 0.4 + gnoise(2.0 * p + vec3(0.0, off, off)) * 0.2 + gnoise(3.0 * p + vec3(0.0, off, off)) * 0.225 + gnoise(4.0 * p + vec3(-off, off, 0.0)) * 0.2).xz;
|
||||
}
|
||||
|
@ -457,13 +429,11 @@ vec3 getBumpMap(vec2 uv) {
|
|||
float fx0y0 = texture2D(baseTexture, uv).r;
|
||||
float fx1y0 = texture2D(baseTexture, uv + vec2(dr.x, 0.0)).r;
|
||||
float fx0y1 = texture2D(baseTexture, uv + vec2(0.0, dr.y)).r;
|
||||
// We get the gradient using partial derivatives
|
||||
vec2 gradient = 0.1 * vec2((fx1y0 - fx0y0) / dr.x, (fx0y1 - fx0y0) / dr.y) + 0.05 * gnoise(vec3(2.0 * uv / texelSize0, 0.0)).xy;
|
||||
// Compute a set of orthonormal basis vectors representing the node's surface plane.
|
||||
vec3 orth1 = normalize(cross(vNormal, mix(vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), step(0.9, abs(vNormal.y)))));
|
||||
vec3 orth2 = normalize(cross(vNormal, orth1));
|
||||
// The normal is computed using the partial derivatives along the texture space x and y axes.
|
||||
// These axes in world space are assumed to be parallel to the basis vectors we defined before.
|
||||
return orth1 * gradient.x + orth2 * gradient.y;
|
||||
vec3 tangent_space = normalize(vec3(gradient, 1.0));
|
||||
// Convert tangent space information to real space
|
||||
return -vTangent * tangent_space.x + vBinormal * tangent_space.y + vNormal * tangent_space.z;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -501,10 +471,10 @@ void main(void)
|
|||
// When applied to all blocks, these bump maps produce irritating Moiré effects.
|
||||
// So we hide the bump maps when close up.
|
||||
float moire_factor = abs(dot(vNormal, viewVec));
|
||||
bump_normal *= mtsmoothstep(0.4 * moire_factor, 0.2 * moire_factor, length(eyeVec) * fov / windowSize.x);
|
||||
fNormal = normalize(vNormal + bump_normal);
|
||||
moire_factor = mtsmoothstep(0.4 * moire_factor, 0.2 * moire_factor, length(eyeVec) * fov / windowSize.x);
|
||||
fNormal = normalize(mix(fNormal, bump_normal, moire_factor));
|
||||
float adj_cosLight = max(1e-5, dot(fNormal, -v_LightDirection));
|
||||
#else
|
||||
#else
|
||||
float adj_cosLight = cosLight;
|
||||
#endif
|
||||
|
||||
|
@ -642,7 +612,7 @@ void main(void)
|
|||
// Note: clarity = (1 - fogginess)
|
||||
float clarity = clamp(fogShadingParameter
|
||||
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
|
||||
|
||||
|
||||
#ifdef ENABLE_TINTED_FOG
|
||||
float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b);
|
||||
// Prevent zero division.
|
||||
|
|
|
@ -7,6 +7,8 @@ uniform highp vec3 cameraOffset;
|
|||
uniform float animationTimer;
|
||||
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vTangent;
|
||||
varying vec3 vBinormal;
|
||||
varying vec3 vPosition;
|
||||
// World position in the visible world (i.e. relative to the cameraOffset.)
|
||||
// This can be used for many shader effects without loss of precision.
|
||||
|
@ -209,6 +211,8 @@ void main(void)
|
|||
normalPass = normalize((inVertexNormal+1)/2);
|
||||
#endif
|
||||
vNormal = inVertexNormal;
|
||||
vTangent = inVertexTangent.xyz;
|
||||
vBinormal = inVertexBinormal.xyz;
|
||||
|
||||
// Calculate color.
|
||||
vec4 color = inVertexColor;
|
||||
|
|
|
@ -111,11 +111,6 @@ vec3 screen_space_dither(highp vec2 frag_coord) {
|
|||
}
|
||||
#endif
|
||||
|
||||
float sFunction(float x, float a) {
|
||||
x = 2.0 * x - 1.0;
|
||||
return 0.5 * sign(x) * pow(abs(x), a) + 0.5;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 uv = varTexCoord.st;
|
||||
|
|
|
@ -53,7 +53,7 @@ float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth)
|
|||
// We use the depth map to approximate the effect of depth on the light intensity.
|
||||
// The exponent was chosen based on aesthetic preference.
|
||||
// To make this phsyically accurate, the brightness here should scale linearly with depth,
|
||||
// but this would make the godrays either too faint or too strong in many cases.
|
||||
// but this would make the godrays either too faint or too strong in many cases.
|
||||
return result / samples * pow(texture2D(depthmap, uv).r, 128.0);
|
||||
#else
|
||||
return result / samples;
|
||||
|
|
|
@ -42,6 +42,26 @@ public:
|
|||
virtual void recalculateNormals(IMeshBuffer *buffer,
|
||||
bool smooth = false, bool angleWeighted = false) const = 0;
|
||||
|
||||
//! Recalculates tangents, requires a tangent mesh
|
||||
/** \param mesh Mesh on which the operation is performed.
|
||||
\param recalculateNormals If the normals shall be recalculated, otherwise original normals of the mesh are used unchanged.
|
||||
\param smooth If the normals shall be smoothed.
|
||||
\param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision.
|
||||
*/
|
||||
virtual void recalculateTangents(IMesh* mesh,
|
||||
bool recalculateNormals = false, bool smooth = false,
|
||||
bool angleWeighted = false) const = 0;
|
||||
|
||||
//! Recalculates tangents, requires a tangent mesh buffer
|
||||
/** \param buffer Meshbuffer on which the operation is performed.
|
||||
\param recalculateNormals If the normals shall be recalculated, otherwise original normals of the buffer are used unchanged.
|
||||
\param smooth If the normals shall be smoothed.
|
||||
\param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision.
|
||||
*/
|
||||
virtual void recalculateTangents(IMeshBuffer* buffer,
|
||||
bool recalculateNormals = false, bool smooth = false,
|
||||
bool angleWeighted = false) const = 0;
|
||||
|
||||
//! Scales the actual mesh, not a scene node.
|
||||
/** \param mesh Mesh on which the operation is performed.
|
||||
\param factor Scale factor for each axis. */
|
||||
|
|
|
@ -80,6 +80,335 @@ void recalculateNormalsT(IMeshBuffer *buffer, bool smooth, bool angleWeighted)
|
|||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void calculateTangents(
|
||||
core::vector3df& normal,
|
||||
core::vector3df& tangent,
|
||||
core::vector3df& binormal,
|
||||
const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices
|
||||
const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords
|
||||
{
|
||||
// choose one of them:
|
||||
//#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers
|
||||
#define USE_IRR_VERSION
|
||||
|
||||
#ifdef USE_IRR_VERSION
|
||||
|
||||
core::vector3df v1 = vt1 - vt2;
|
||||
core::vector3df v2 = vt3 - vt1;
|
||||
normal = v2.crossProduct(v1);
|
||||
normal.normalize();
|
||||
|
||||
// binormal
|
||||
|
||||
f32 deltaX1 = tc1.X - tc2.X;
|
||||
f32 deltaX2 = tc3.X - tc1.X;
|
||||
binormal = (v1 * deltaX2) - (v2 * deltaX1);
|
||||
binormal.normalize();
|
||||
|
||||
// tangent
|
||||
|
||||
f32 deltaY1 = tc1.Y - tc2.Y;
|
||||
f32 deltaY2 = tc3.Y - tc1.Y;
|
||||
tangent = (v1 * deltaY2) - (v2 * deltaY1);
|
||||
tangent.normalize();
|
||||
|
||||
// adjust
|
||||
|
||||
core::vector3df txb = tangent.crossProduct(binormal);
|
||||
if (txb.dotProduct(normal) < 0.0f)
|
||||
{
|
||||
tangent *= -1.0f;
|
||||
binormal *= -1.0f;
|
||||
}
|
||||
|
||||
#endif // USE_IRR_VERSION
|
||||
|
||||
#ifdef USE_NVIDIA_GLH_VERSION
|
||||
|
||||
tangent.set(0, 0, 0);
|
||||
binormal.set(0, 0, 0);
|
||||
|
||||
core::vector3df v1(vt2.X - vt1.X, tc2.X - tc1.X, tc2.Y - tc1.Y);
|
||||
core::vector3df v2(vt3.X - vt1.X, tc3.X - tc1.X, tc3.Y - tc1.Y);
|
||||
|
||||
core::vector3df txb = v1.crossProduct(v2);
|
||||
if (!core::iszero(txb.X))
|
||||
{
|
||||
tangent.X = -txb.Y / txb.X;
|
||||
binormal.X = -txb.Z / txb.X;
|
||||
}
|
||||
|
||||
v1.X = vt2.Y - vt1.Y;
|
||||
v2.X = vt3.Y - vt1.Y;
|
||||
txb = v1.crossProduct(v2);
|
||||
|
||||
if (!core::iszero(txb.X))
|
||||
{
|
||||
tangent.Y = -txb.Y / txb.X;
|
||||
binormal.Y = -txb.Z / txb.X;
|
||||
}
|
||||
|
||||
v1.X = vt2.Z - vt1.Z;
|
||||
v2.X = vt3.Z - vt1.Z;
|
||||
txb = v1.crossProduct(v2);
|
||||
|
||||
if (!core::iszero(txb.X))
|
||||
{
|
||||
tangent.Z = -txb.Y / txb.X;
|
||||
binormal.Z = -txb.Z / txb.X;
|
||||
}
|
||||
|
||||
tangent.normalize();
|
||||
binormal.normalize();
|
||||
|
||||
normal = tangent.crossProduct(binormal);
|
||||
normal.normalize();
|
||||
|
||||
binormal = tangent.crossProduct(normal);
|
||||
binormal.normalize();
|
||||
|
||||
core::plane3d<f32> pl(vt1, vt2, vt3);
|
||||
|
||||
if (normal.dotProduct(pl.Normal) < 0.0f)
|
||||
normal *= -1.0f;
|
||||
|
||||
#endif // USE_NVIDIA_GLH_VERSION
|
||||
}
|
||||
|
||||
|
||||
//! Recalculates tangents for a tangent mesh buffer
|
||||
template <typename T>
|
||||
void recalculateTangentsT(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted)
|
||||
{
|
||||
if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS))
|
||||
return;
|
||||
|
||||
const u32 vtxCnt = buffer->getVertexCount();
|
||||
const u32 idxCnt = buffer->getIndexCount();
|
||||
|
||||
T* idx = reinterpret_cast<T*>(buffer->getIndices());
|
||||
video::S3DVertexTangents* v =
|
||||
(video::S3DVertexTangents*)buffer->getVertices();
|
||||
|
||||
if (smooth)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i != vtxCnt; ++i)
|
||||
{
|
||||
if (recalculateNormals)
|
||||
v[i].Normal.set(0.f, 0.f, 0.f);
|
||||
v[i].Tangent.set(0.f, 0.f, 0.f);
|
||||
v[i].Binormal.set(0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
//Each vertex gets the sum of the tangents and binormals from the faces around it
|
||||
for (i = 0; i < idxCnt; i += 3)
|
||||
{
|
||||
// if this triangle is degenerate, skip it!
|
||||
if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos ||
|
||||
v[idx[i + 0]].Pos == v[idx[i + 2]].Pos ||
|
||||
v[idx[i + 1]].Pos == v[idx[i + 2]].Pos
|
||||
/*||
|
||||
v[idx[i+0]].TCoords == v[idx[i+1]].TCoords ||
|
||||
v[idx[i+0]].TCoords == v[idx[i+2]].TCoords ||
|
||||
v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */
|
||||
)
|
||||
continue;
|
||||
|
||||
//Angle-weighted normals look better, but are slightly more CPU intensive to calculate
|
||||
core::vector3df weight(1.f, 1.f, 1.f);
|
||||
if (angleWeighted)
|
||||
weight = irr::scene::getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos); // writing irr::scene:: necessary for borland
|
||||
core::vector3df localNormal;
|
||||
core::vector3df localTangent;
|
||||
core::vector3df localBinormal;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
localTangent,
|
||||
localBinormal,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].TCoords,
|
||||
v[idx[i + 1]].TCoords,
|
||||
v[idx[i + 2]].TCoords);
|
||||
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 0]].Normal += localNormal * weight.X;
|
||||
v[idx[i + 0]].Tangent += localTangent * weight.X;
|
||||
v[idx[i + 0]].Binormal += localBinormal * weight.X;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
localTangent,
|
||||
localBinormal,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].TCoords,
|
||||
v[idx[i + 2]].TCoords,
|
||||
v[idx[i + 0]].TCoords);
|
||||
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 1]].Normal += localNormal * weight.Y;
|
||||
v[idx[i + 1]].Tangent += localTangent * weight.Y;
|
||||
v[idx[i + 1]].Binormal += localBinormal * weight.Y;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
localTangent,
|
||||
localBinormal,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].TCoords,
|
||||
v[idx[i + 0]].TCoords,
|
||||
v[idx[i + 1]].TCoords);
|
||||
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 2]].Normal += localNormal * weight.Z;
|
||||
v[idx[i + 2]].Tangent += localTangent * weight.Z;
|
||||
v[idx[i + 2]].Binormal += localBinormal * weight.Z;
|
||||
}
|
||||
|
||||
// Normalize the tangents and binormals
|
||||
if (recalculateNormals)
|
||||
{
|
||||
for (i = 0; i != vtxCnt; ++i)
|
||||
v[i].Normal.normalize();
|
||||
}
|
||||
for (i = 0; i != vtxCnt; ++i)
|
||||
{
|
||||
v[i].Tangent.normalize();
|
||||
v[i].Binormal.normalize();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
core::vector3df localNormal;
|
||||
for (u32 i = 0; i < idxCnt; i += 3)
|
||||
{
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
v[idx[i + 0]].Tangent,
|
||||
v[idx[i + 0]].Binormal,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].TCoords,
|
||||
v[idx[i + 1]].TCoords,
|
||||
v[idx[i + 2]].TCoords);
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 0]].Normal = localNormal;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
v[idx[i + 1]].Tangent,
|
||||
v[idx[i + 1]].Binormal,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].TCoords,
|
||||
v[idx[i + 2]].TCoords,
|
||||
v[idx[i + 0]].TCoords);
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 1]].Normal = localNormal;
|
||||
|
||||
calculateTangents(
|
||||
localNormal,
|
||||
v[idx[i + 2]].Tangent,
|
||||
v[idx[i + 2]].Binormal,
|
||||
v[idx[i + 2]].Pos,
|
||||
v[idx[i + 0]].Pos,
|
||||
v[idx[i + 1]].Pos,
|
||||
v[idx[i + 2]].TCoords,
|
||||
v[idx[i + 0]].TCoords,
|
||||
v[idx[i + 1]].TCoords);
|
||||
if (recalculateNormals)
|
||||
v[idx[i + 2]].Normal = localNormal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Recalculates tangents for a tangent mesh buffer
|
||||
void CMeshManipulator::recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) const
|
||||
{
|
||||
if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS))
|
||||
{
|
||||
if (buffer->getIndexType() == video::EIT_16BIT)
|
||||
recalculateTangentsT<u16>(buffer, recalculateNormals, smooth, angleWeighted);
|
||||
else
|
||||
recalculateTangentsT<u32>(buffer, recalculateNormals, smooth, angleWeighted);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Recalculates tangents for all tangent mesh buffers
|
||||
void CMeshManipulator::recalculateTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const
|
||||
{
|
||||
if (!mesh)
|
||||
return;
|
||||
|
||||
const u32 meshBufferCount = mesh->getMeshBufferCount();
|
||||
for (u32 b = 0; b < meshBufferCount; ++b)
|
||||
{
|
||||
recalculateTangents(mesh->getMeshBuffer(b), recalculateNormals, smooth, angleWeighted);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Creates a planar texture mapping on the meshbuffer
|
||||
template<typename T>
|
||||
void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolution)
|
||||
{
|
||||
u32 idxcnt = buffer->getIndexCount();
|
||||
T* idx = reinterpret_cast<T*>(buffer->getIndices());
|
||||
|
||||
for (u32 i = 0; i < idxcnt; i += 3)
|
||||
{
|
||||
core::plane3df p(buffer->getPosition(idx[i + 0]), buffer->getPosition(idx[i + 1]), buffer->getPosition(idx[i + 2]));
|
||||
p.Normal.X = fabsf(p.Normal.X);
|
||||
p.Normal.Y = fabsf(p.Normal.Y);
|
||||
p.Normal.Z = fabsf(p.Normal.Z);
|
||||
// calculate planar mapping worldspace coordinates
|
||||
|
||||
if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z)
|
||||
{
|
||||
for (u32 o = 0; o != 3; ++o)
|
||||
{
|
||||
buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).Y * resolution;
|
||||
buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Z * resolution;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z)
|
||||
{
|
||||
for (u32 o = 0; o != 3; ++o)
|
||||
{
|
||||
buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).X * resolution;
|
||||
buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Z * resolution;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 o = 0; o != 3; ++o)
|
||||
{
|
||||
buffer->getTCoords(idx[i + o]).X = buffer->getPosition(idx[i + o]).X * resolution;
|
||||
buffer->getTCoords(idx[i + o]).Y = buffer->getPosition(idx[i + o]).Y * resolution;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Recalculates all normals of the mesh buffer.
|
||||
/** \param buffer: Mesh buffer on which the operation is performed. */
|
||||
void CMeshManipulator::recalculateNormals(IMeshBuffer *buffer, bool smooth, bool angleWeighted) const
|
||||
|
|
|
@ -29,6 +29,12 @@ public:
|
|||
\param smooth: Whether to use smoothed normals. */
|
||||
void recalculateNormals(IMeshBuffer *buffer, bool smooth = false, bool angleWeighted = false) const override;
|
||||
|
||||
//! Recalculates tangents, requires a tangent mesh buffer
|
||||
virtual void recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Recalculates tangents, requires a tangent mesh
|
||||
virtual void recalculateTangents(IMesh* mesh, bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Clones a static IMesh into a modifiable SMesh.
|
||||
SMesh *createMeshCopy(scene::IMesh *mesh) const override;
|
||||
|
||||
|
|
|
@ -40,10 +40,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
MeshMakeData
|
||||
*/
|
||||
|
||||
MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders):
|
||||
MeshMakeData::MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders, bool use_tangent_vertices):
|
||||
side_length(side_length),
|
||||
nodedef(ndef),
|
||||
m_use_shaders(use_shaders)
|
||||
m_use_shaders(use_shaders),
|
||||
m_use_tangent_vertices(use_tangent_vertices)
|
||||
{}
|
||||
|
||||
void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos)
|
||||
|
@ -617,6 +618,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
|
|||
for (auto &m : m_mesh)
|
||||
m = make_irr<scene::SMesh>();
|
||||
m_enable_shaders = data->m_use_shaders;
|
||||
m_use_tangent_vertices = data->m_use_tangent_vertices;
|
||||
|
||||
auto mesh_grid = client->getMeshGrid();
|
||||
v3s16 bp = data->m_blockpos;
|
||||
|
@ -752,27 +754,44 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
|
|||
p.layer.applyMaterialOptions(material);
|
||||
}
|
||||
|
||||
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->Material = material;
|
||||
if (p.layer.isTransparent()) {
|
||||
buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0);
|
||||
|
||||
MeshTriangle t;
|
||||
t.buffer = buf;
|
||||
m_transparent_triangles.reserve(p.indices.size() / 3);
|
||||
for (u32 i = 0; i < p.indices.size(); i += 3) {
|
||||
t.p1 = p.indices[i];
|
||||
t.p2 = p.indices[i + 1];
|
||||
t.p3 = p.indices[i + 2];
|
||||
t.updateAttributes();
|
||||
m_transparent_triangles.push_back(t);
|
||||
}
|
||||
} else {
|
||||
buf->append(&p.vertices[0], p.vertices.size(),
|
||||
if (m_use_tangent_vertices && !p.layer.isTransparent()) {
|
||||
scene::SMeshBufferTangents* buf = new scene::SMeshBufferTangents();
|
||||
buf->Material = material;
|
||||
std::vector<video::S3DVertexTangents> vertices;
|
||||
vertices.reserve(p.vertices.size());
|
||||
for (video::S3DVertex &v : p.vertices)
|
||||
vertices.push_back(video::S3DVertexTangents(v.Pos, v.Normal, v.Color, v.TCoords));
|
||||
buf->append(&vertices[0], vertices.size(),
|
||||
&p.indices[0], p.indices.size());
|
||||
buf->recalculateBoundingBox();
|
||||
scene::IMeshManipulator* meshmanip =
|
||||
client->getSceneManager()->getMeshManipulator();
|
||||
meshmanip->recalculateTangents(buf);
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
} else {
|
||||
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->Material = material;
|
||||
if (p.layer.isTransparent()) {
|
||||
buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0);
|
||||
|
||||
MeshTriangle t;
|
||||
t.buffer = buf;
|
||||
m_transparent_triangles.reserve(p.indices.size() / 3);
|
||||
for (u32 i = 0; i < p.indices.size(); i += 3) {
|
||||
t.p1 = p.indices[i];
|
||||
t.p2 = p.indices[i + 1];
|
||||
t.p3 = p.indices[i + 2];
|
||||
t.updateAttributes();
|
||||
m_transparent_triangles.push_back(t);
|
||||
}
|
||||
} else {
|
||||
buf->append(&p.vertices[0], p.vertices.size(),
|
||||
&p.indices[0], p.indices.size());
|
||||
}
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->drop();
|
||||
}
|
||||
|
||||
if (mesh) {
|
||||
|
|
|
@ -51,8 +51,9 @@ struct MeshMakeData
|
|||
|
||||
const NodeDefManager *nodedef;
|
||||
bool m_use_shaders;
|
||||
bool m_use_tangent_vertices;
|
||||
|
||||
MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders);
|
||||
MeshMakeData(const NodeDefManager *ndef, u16 side_length, bool use_shaders, bool use_tangent_vertices = false);
|
||||
|
||||
/*
|
||||
Copy block data manually (to allow optimizations by the caller)
|
||||
|
@ -251,6 +252,7 @@ private:
|
|||
v3f m_bounding_sphere_center;
|
||||
|
||||
bool m_enable_shaders;
|
||||
bool m_use_tangent_vertices;
|
||||
|
||||
// Must animate() be called before rendering?
|
||||
bool m_has_animation;
|
||||
|
|
|
@ -55,6 +55,7 @@ MeshUpdateQueue::MeshUpdateQueue(Client *client):
|
|||
m_client(client)
|
||||
{
|
||||
m_cache_enable_shaders = g_settings->getBool("enable_shaders");
|
||||
m_cache_use_tangent_vertices = m_cache_enable_shaders && g_settings->getBool("enable_bumpmaps");
|
||||
m_cache_smooth_lighting = g_settings->getBool("smooth_lighting");
|
||||
}
|
||||
|
||||
|
@ -192,7 +193,7 @@ void MeshUpdateQueue::done(v3s16 pos)
|
|||
void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q)
|
||||
{
|
||||
auto mesh_grid = m_client->getMeshGrid();
|
||||
MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_enable_shaders);
|
||||
MeshMakeData *data = new MeshMakeData(m_client->ndef(), MAP_BLOCKSIZE * mesh_grid.cell_size, m_cache_enable_shaders, m_cache_use_tangent_vertices);
|
||||
q->data = data;
|
||||
|
||||
data->fillBlockDataBegin(q->p);
|
||||
|
|
|
@ -86,6 +86,7 @@ private:
|
|||
|
||||
// TODO: Add callback to update these when g_settings changes
|
||||
bool m_cache_enable_shaders;
|
||||
bool m_cache_use_tangent_vertices;
|
||||
bool m_cache_smooth_lighting;
|
||||
|
||||
void fillDataFromMapBlocks(QueuedMeshUpdate *q);
|
||||
|
|
|
@ -68,7 +68,7 @@ struct Vignette {
|
|||
* Colors in ASL CDL follow the following equation:
|
||||
*
|
||||
* out = pow(in * slope + offset, power)
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct ColorDecisionList {
|
||||
core::vector3df slope{1.2, 1.0, 0.8};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue