Use vertices with tangents only when its needed.

This commit is contained in:
RealBadAngel 2016-02-12 12:25:20 +01:00 committed by paramat
parent 3a74b84007
commit 7ea40e45b1
4 changed files with 131 additions and 67 deletions

@ -263,6 +263,9 @@ Client::Client(
m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); m_cache_smooth_lighting = g_settings->getBool("smooth_lighting");
m_cache_enable_shaders = g_settings->getBool("enable_shaders"); m_cache_enable_shaders = g_settings->getBool("enable_shaders");
m_cache_use_tangent_vertices = m_cache_enable_shaders && (
g_settings->getBool("enable_bumpmapping") ||
g_settings->getBool("enable_parallax_occlusion"));
} }
void Client::Stop() void Client::Stop()
@ -1582,7 +1585,8 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent)
Create a task to update the mesh of the block Create a task to update the mesh of the block
*/ */
MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders); MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders,
m_cache_use_tangent_vertices);
{ {
//TimeTaker timer("data fill"); //TimeTaker timer("data fill");

@ -677,6 +677,7 @@ private:
// TODO: Add callback to update these when g_settings changes // TODO: Add callback to update these when g_settings changes
bool m_cache_smooth_lighting; bool m_cache_smooth_lighting;
bool m_cache_enable_shaders; bool m_cache_enable_shaders;
bool m_cache_use_tangent_vertices;
DISABLE_CLASS_COPY(Client); DISABLE_CLASS_COPY(Client);
}; };

@ -33,24 +33,26 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/directiontables.h" #include "util/directiontables.h"
#include <IMeshManipulator.h> #include <IMeshManipulator.h>
static void applyFacesShading(video::SColor& color, float factor) static void applyFacesShading(video::SColor &color, const float factor)
{ {
color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255)); color.setRed(core::clamp(core::round32(color.getRed() * factor), 0, 255));
color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255)); color.setGreen(core::clamp(core::round32(color.getGreen() * factor), 0, 255));
} }
/* /*
MeshMakeData MeshMakeData
*/ */
MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders): MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders,
bool use_tangent_vertices):
m_vmanip(), m_vmanip(),
m_blockpos(-1337,-1337,-1337), m_blockpos(-1337,-1337,-1337),
m_crack_pos_relative(-1337, -1337, -1337), m_crack_pos_relative(-1337, -1337, -1337),
m_smooth_lighting(false), m_smooth_lighting(false),
m_show_hud(false), m_show_hud(false),
m_gamedef(gamedef), m_gamedef(gamedef),
m_use_shaders(use_shaders) m_use_shaders(use_shaders),
m_use_tangent_vertices(use_tangent_vertices)
{} {}
void MeshMakeData::fill(MapBlock *block) void MeshMakeData::fill(MapBlock *block)
@ -1032,6 +1034,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
m_daynight_diffs() m_daynight_diffs()
{ {
m_enable_shaders = data->m_use_shaders; m_enable_shaders = data->m_use_shaders;
m_use_tangent_vertices = data->m_use_tangent_vertices;
if (g_settings->getBool("enable_minimap")) { if (g_settings->getBool("enable_minimap")) {
m_minimap_mapblock = new MinimapMapblock; m_minimap_mapblock = new MinimapMapblock;
@ -1064,15 +1067,14 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
Convert FastFaces to MeshCollector Convert FastFaces to MeshCollector
*/ */
MeshCollector collector; MeshCollector collector(m_use_tangent_vertices);
{ {
// avg 0ms (100ms spikes when loading textures the first time) // avg 0ms (100ms spikes when loading textures the first time)
// (NOTE: probably outdated) // (NOTE: probably outdated)
//TimeTaker timer2("MeshCollector building"); //TimeTaker timer2("MeshCollector building");
for(u32 i=0; i<fastfaces_new.size(); i++) for (u32 i = 0; i < fastfaces_new.size(); i++) {
{
FastFace &f = fastfaces_new[i]; FastFace &f = fastfaces_new[i];
const u16 indices[] = {0,1,2,2,3,0}; const u16 indices[] = {0,1,2,2,3,0};
@ -1150,35 +1152,43 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
p.tile.texture = animation_frame.texture; p.tile.texture = animation_frame.texture;
} }
for(u32 j = 0; j < p.vertices.size(); j++) u32 vertex_count = m_use_tangent_vertices ?
{ p.tangent_vertices.size() : p.vertices.size();
video::S3DVertex *vertex = &p.vertices[j]; for (u32 j = 0; j < vertex_count; j++) {
v3f *Normal;
video::SColor *vc;
if (m_use_tangent_vertices) {
vc = &p.tangent_vertices[j].Color;
Normal = &p.tangent_vertices[j].Normal;
} else {
vc = &p.vertices[j].Color;
Normal = &p.vertices[j].Normal;
}
// Note applyFacesShading second parameter is precalculated sqrt // Note applyFacesShading second parameter is precalculated sqrt
// value for speed improvement // value for speed improvement
// Skip it for lightsources and top faces. // Skip it for lightsources and top faces.
video::SColor &vc = vertex->Color; if (!vc->getBlue()) {
if (!vc.getBlue()) { if (Normal->Y < -0.5) {
if (vertex->Normal.Y < -0.5) { applyFacesShading(*vc, 0.447213);
applyFacesShading (vc, 0.447213); } else if (Normal->X > 0.5) {
} else if (vertex->Normal.X > 0.5) { applyFacesShading(*vc, 0.670820);
applyFacesShading (vc, 0.670820); } else if (Normal->X < -0.5) {
} else if (vertex->Normal.X < -0.5) { applyFacesShading(*vc, 0.670820);
applyFacesShading (vc, 0.670820); } else if (Normal->Z > 0.5) {
} else if (vertex->Normal.Z > 0.5) { applyFacesShading(*vc, 0.836660);
applyFacesShading (vc, 0.836660); } else if (Normal->Z < -0.5) {
} else if (vertex->Normal.Z < -0.5) { applyFacesShading(*vc, 0.836660);
applyFacesShading (vc, 0.836660);
} }
} }
if(!m_enable_shaders) if (!m_enable_shaders) {
{
// - Classic lighting (shaders handle this by themselves) // - Classic lighting (shaders handle this by themselves)
// Set initial real color and store for later updates // Set initial real color and store for later updates
u8 day = vc.getRed(); u8 day = vc->getRed();
u8 night = vc.getGreen(); u8 night = vc->getGreen();
finalColorBlend(vc, day, night, 1000); finalColorBlend(*vc, day, night, 1000);
if(day != night) if (day != night) {
m_daynight_diffs[i][j] = std::make_pair(day, night); m_daynight_diffs[i][j] = std::make_pair(day, night);
}
} }
} }
@ -1201,34 +1211,46 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
p.tile.applyMaterialOptions(material); p.tile.applyMaterialOptions(material);
} }
// Create meshbuffer scene::SMesh *mesh = (scene::SMesh *)m_mesh;
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
// Set material // Create meshbuffer, add to mesh
buf->Material = material; if (m_use_tangent_vertices) {
// Add to mesh scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
scene::SMesh *mesh = (scene::SMesh *)m_mesh; // Set material
mesh->addMeshBuffer(buf); buf->Material = material;
// Mesh grabbed it // Add to mesh
buf->drop(); mesh->addMeshBuffer(buf);
buf->append(&p.vertices[0], p.vertices.size(), // Mesh grabbed it
&p.indices[0], p.indices.size()); buf->drop();
} buf->append(&p.tangent_vertices[0], p.tangent_vertices.size(),
m_camera_offset = camera_offset; &p.indices[0], p.indices.size());
} else {
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
// Set material
buf->Material = material;
// Add to mesh
mesh->addMeshBuffer(buf);
// Mesh grabbed it
buf->drop();
buf->append(&p.vertices[0], p.vertices.size(),
&p.indices[0], p.indices.size());
}
}
/* /*
Do some stuff to the mesh Do some stuff to the mesh
*/ */
m_camera_offset = camera_offset;
translateMesh(m_mesh,
intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS)); if (m_use_tangent_vertices) {
scene::IMeshManipulator* meshmanip =
if (m_enable_shaders) { m_gamedef->getSceneManager()->getMeshManipulator();
scene::IMeshManipulator* meshmanip = m_gamedef->getSceneManager()->getMeshManipulator(); meshmanip->recalculateTangents(m_mesh, true, false, false);
scene::IMesh* tangentMesh = meshmanip->createMeshWithTangents(m_mesh);
m_mesh->drop();
m_mesh = tangentMesh;
} }
if(m_mesh) if (m_mesh)
{ {
#if 0 #if 0
// Usually 1-700 faces and 1-7 materials // Usually 1-700 faces and 1-7 materials
@ -1400,17 +1422,30 @@ void MeshCollector::append(const TileSpec &tile,
p = &prebuffers[prebuffers.size() - 1]; p = &prebuffers[prebuffers.size() - 1];
} }
u32 vertex_count = p->vertices.size(); u32 vertex_count;
for (u32 i = 0; i < numIndices; i++) { if (m_use_tangent_vertices) {
vertex_count = p->tangent_vertices.size();
p->tangent_vertices.reserve(vertex_count + numVertices);
for (u32 i = 0; i < numVertices; i++) {
video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal,
vertices[i].Color, vertices[i].TCoords);
p->tangent_vertices.push_back(vert);
}
} else {
vertex_count = p->vertices.size();
p->vertices.reserve(vertex_count + numVertices);
for (u32 i = 0; i < numVertices; i++) {
video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal,
vertices[i].Color, vertices[i].TCoords);
p->vertices.push_back(vert);
}
}
p->indices.reserve(p->indices.size() + numIndices);
for (u32 i = 0; i < numIndices; i++) {
u32 j = indices[i] + vertex_count; u32 j = indices[i] + vertex_count;
p->indices.push_back(j); p->indices.push_back(j);
} }
for (u32 i = 0; i < numVertices; i++) {
video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal,
vertices[i].Color, vertices[i].TCoords);
p->vertices.push_back(vert);
}
} }
/* /*
@ -1446,15 +1481,28 @@ void MeshCollector::append(const TileSpec &tile,
p = &prebuffers[prebuffers.size() - 1]; p = &prebuffers[prebuffers.size() - 1];
} }
u32 vertex_count = p->vertices.size(); u32 vertex_count;
if (m_use_tangent_vertices) {
vertex_count = p->tangent_vertices.size();
p->tangent_vertices.reserve(vertex_count + numVertices);
for (u32 i = 0; i < numVertices; i++) {
video::S3DVertexTangents vert(vertices[i].Pos + pos,
vertices[i].Normal, c, vertices[i].TCoords);
p->tangent_vertices.push_back(vert);
}
} else {
vertex_count = p->vertices.size();
p->vertices.reserve(vertex_count + numVertices);
for (u32 i = 0; i < numVertices; i++) {
video::S3DVertex vert(vertices[i].Pos + pos,
vertices[i].Normal, c, vertices[i].TCoords);
p->vertices.push_back(vert);
}
}
p->indices.reserve(p->indices.size() + numIndices);
for (u32 i = 0; i < numIndices; i++) { for (u32 i = 0; i < numIndices; i++) {
u32 j = indices[i] + vertex_count; u32 j = indices[i] + vertex_count;
p->indices.push_back(j); p->indices.push_back(j);
} }
for (u32 i = 0; i < numVertices; i++) {
video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal,
c, vertices[i].TCoords);
p->vertices.push_back(vert);
}
} }

@ -46,8 +46,10 @@ struct MeshMakeData
IGameDef *m_gamedef; IGameDef *m_gamedef;
bool m_use_shaders; bool m_use_shaders;
bool m_use_tangent_vertices;
MeshMakeData(IGameDef *gamedef, bool use_shaders); MeshMakeData(IGameDef *gamedef, bool use_shaders,
bool use_tangent_vertices = false);
/* /*
Copy central data directly from block, and other data from Copy central data directly from block, and other data from
@ -130,6 +132,7 @@ private:
IShaderSource *m_shdrsrc; IShaderSource *m_shdrsrc;
bool m_enable_shaders; bool m_enable_shaders;
bool m_use_tangent_vertices;
// Must animate() be called before rendering? // Must animate() be called before rendering?
bool m_has_animation; bool m_has_animation;
@ -167,11 +170,19 @@ struct PreMeshBuffer
TileSpec tile; TileSpec tile;
std::vector<u16> indices; std::vector<u16> indices;
std::vector<video::S3DVertex> vertices; std::vector<video::S3DVertex> vertices;
std::vector<video::S3DVertexTangents> tangent_vertices;
}; };
struct MeshCollector struct MeshCollector
{ {
std::vector<PreMeshBuffer> prebuffers; std::vector<PreMeshBuffer> prebuffers;
bool m_use_tangent_vertices;
MeshCollector(bool use_tangent_vertices):
m_use_tangent_vertices(use_tangent_vertices)
{
}
void append(const TileSpec &material, void append(const TileSpec &material,
const video::S3DVertex *vertices, u32 numVertices, const video::S3DVertex *vertices, u32 numVertices,
const u16 *indices, u32 numIndices); const u16 *indices, u32 numIndices);