Fixing particles

This commit is contained in:
Vladislav Khorev 2026-03-08 19:07:02 +03:00
parent 9da3cc4401
commit 59b5bea540
11 changed files with 182 additions and 123 deletions

View File

@ -5,7 +5,7 @@
"texture": "resources/spark_white.png", "texture": "resources/spark_white.png",
"speedRange": [10.0, 30.0], "speedRange": [10.0, 30.0],
"zSpeedRange": [-1.0, 1.0], "zSpeedRange": [-1.0, 1.0],
"scaleRange": [0.5, 1.0], "scaleRange": [5.0, 10.0],
"lifeTimeRange": [200.0, 800.0], "lifeTimeRange": [200.0, 800.0],
"emissionRate": 50.0, "emissionRate": 50.0,
"maxParticles": 5, "maxParticles": 5,

View File

@ -1,20 +1,14 @@
{ {
"emissionRate": 100, "emissionRate": 0.4,
"maxParticles": 200, "maxParticles": 400,
"particleSize": 0.3, "particleSize": 0.3,
"biasX": 0.3, "biasX": 0.3,
"emissionPoints": [ "emissionPoints": [
{
"position": [-1.0, 1.4, -3.5]
},
{
"position": [1.0, 1.4, -3.5]
}
], ],
"speedRange": [0.5, 2.0], "speedRange": [0.5, 2.0],
"zSpeedRange": [1.0, 3.0], "zSpeedRange": [1.0, 3.0],
"scaleRange": [0.8, 1.2], "scaleRange": [0.8, 1.2],
"lifeTimeRange": [600.0, 1400.0], "lifeTimeRange": [300.0, 500.0],
"texture": "resources/spark.png", "texture": "resources/spark.png",
"shaderProgramName": "spark" "shaderProgramName": "spark"
} }

View File

@ -1,6 +1,6 @@
{ {
"emissionRate": 10.0, "emissionRate": 0.4,
"maxParticles": 200, "maxParticles": 400,
"particleSize": 0.3, "particleSize": 0.3,
"biasX": 0.3, "biasX": 0.3,
"emissionPoints": [ "emissionPoints": [

View File

@ -334,8 +334,10 @@ namespace ZL
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//processTickCount();
drawScene(); drawScene();
processTickCount(); processTickCount();
//std::this_thread::sleep_for(std::chrono::milliseconds(50));
SDL_GL_SwapWindow(ZL::Environment::window); SDL_GL_SwapWindow(ZL::Environment::window);
} }
@ -390,19 +392,16 @@ namespace ZL
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth); int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight); int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
handleDown(static_cast<int64_t>(event.tfinger.fingerId), mx, my); handleDown(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
//std::cout << "Finger down: id=" << event.tfinger.fingerId << " x=" << mx << " y=" << my << std::endl;
} }
else if (event.type == SDL_FINGERUP) { else if (event.type == SDL_FINGERUP) {
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth); int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight); int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
handleUp(static_cast<int64_t>(event.tfinger.fingerId), mx, my); handleUp(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
//std::cout << "Finger up: id=" << event.tfinger.fingerId << " x=" << mx << " y=" << my << std::endl;
} }
else if (event.type == SDL_FINGERMOTION) { else if (event.type == SDL_FINGERMOTION) {
int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth); int mx = static_cast<int>(event.tfinger.x * Environment::projectionWidth);
int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight); int my = static_cast<int>(event.tfinger.y * Environment::projectionHeight);
handleMotion(static_cast<int64_t>(event.tfinger.fingerId), mx, my); handleMotion(static_cast<int64_t>(event.tfinger.fingerId), mx, my);
//std::cout << "Finger motion: id=" << event.tfinger.fingerId << " x=" << mx << " y=" << my << std::endl;
} }
#endif #endif

View File

@ -506,9 +506,11 @@ namespace ZL
renderer.DrawVertexRenderStruct(spaceship); renderer.DrawVertexRenderStruct(spaceship);
} }
renderer.PushMatrix(); renderer.PushMatrix();
renderer.RotateMatrix(Environment::inverseShipMatrix); renderer.RotateMatrix(Environment::inverseShipMatrix);
renderer.TranslateMatrix(-Environment::shipState.position); renderer.TranslateMatrix(- /*0.5 * */ Environment::shipState.position);
std::cout << "Ship pos draw: " << Environment::shipState.position.transpose() << "\n";
if (Environment::shipState.shipType == 1) { if (Environment::shipState.shipType == 1) {
sparkEmitterCargo.draw(renderer, Environment::zoom, Environment::width, Environment::height); sparkEmitterCargo.draw(renderer, Environment::zoom, Environment::width, Environment::height);
} }
@ -541,21 +543,6 @@ namespace ZL
renderer.shaderManager.PopShader(); renderer.shaderManager.PopShader();
/*
if (shipAlive) {
renderer.PushMatrix();
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
renderer.RotateMatrix(Environment::inverseShipMatrix);
renderer.TranslateMatrix(-Environment::shipState.position);
if (Environment::shipState.shipType == 1) {
sparkEmitterCargo.draw(renderer, Environment::zoom, Environment::width, Environment::height);
}
else {
sparkEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
}
renderer.PopMatrix();
}*/
if (showExplosion) { if (showExplosion) {
explosionEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height, false); explosionEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height, false);
} }
@ -604,6 +591,17 @@ namespace ZL
glViewport(0, 0, Environment::width, Environment::height); glViewport(0, 0, Environment::width, Environment::height);
// Готовим данные всех эмиттеров (CPU + VBO upload) до начала отрисовки,
// чтобы draw() делал только GPU-вызовы без пауз между кораблём и частицами.
sparkEmitter.prepareForDraw(true);
sparkEmitterCargo.prepareForDraw(true);
explosionEmitter.prepareForDraw(false);
for (const auto& p : projectiles) {
if (p && p->isActive()) {
p->projectileEmitter.prepareForDraw(true);
}
}
CheckGlError(); CheckGlError();
float skyPercent = 0.0; float skyPercent = 0.0;
@ -1437,35 +1435,6 @@ namespace ZL
auto now_ms = newTickCount; auto now_ms = newTickCount;
SparkEmitter* sparkEmitterPtr;
if (Environment::shipState.shipType == 1) {
sparkEmitterPtr = &sparkEmitterCargo;
static std::vector<Vector3f> emissionPoints = { Vector3f(0, 0, 0), Vector3f(0, 0, 0) };
emissionPoints[0] = Environment::shipState.position + Environment::shipState.rotation * Vector3f{ 0.0, 2.8, -3.5 + 16.0 };
emissionPoints[1] = Environment::shipState.position + Environment::shipState.rotation * Vector3f{ 0.0, 1.5, -3.5 + 16.0 };
sparkEmitterPtr->setEmissionPoints(emissionPoints);
}
else
{
sparkEmitterPtr = &sparkEmitter;
static std::vector<Vector3f> emissionPoints = { Vector3f(0, 0, 0), Vector3f(0, 0, 0) };
emissionPoints[0] = Environment::shipState.position + Environment::shipState.rotation * Vector3f{-1.0, 1.4-1.0, -3.5 + 16.0};
emissionPoints[1] = Environment::shipState.position + Environment::shipState.rotation * Vector3f{1.0, 1.4 - 1.0, -3.5 + 16.0 };
sparkEmitterPtr->setEmissionPoints(emissionPoints);
}
if (Environment::shipState.velocity > 0.1f)
{
sparkEmitterPtr->setIsActive(true);
}
else
{
sparkEmitterPtr->setIsActive(false);
}
sparkEmitterPtr->update(static_cast<float>(delta));
if (firePressed) if (firePressed)
{ {
firePressed = false; firePressed = false;
@ -1576,6 +1545,41 @@ namespace ZL
} }
//--------------
SparkEmitter* sparkEmitterPtr;
if (Environment::shipState.shipType == 1) {
sparkEmitterPtr = &sparkEmitterCargo;
static std::vector<Vector3f> emissionPoints = { Vector3f(0, 0, 0), Vector3f(0, 0, 0) };
emissionPoints[0] = Environment::shipState.position + Environment::shipState.rotation * Vector3f{ 0.0, 2.8, -6.5 + 16.0 };
emissionPoints[1] = Environment::shipState.position + Environment::shipState.rotation * Vector3f{ 0.0, 1.5, -6.5 + 16.0 };
sparkEmitterPtr->setEmissionPoints(emissionPoints);
}
else
{
sparkEmitterPtr = &sparkEmitter;
static std::vector<Vector3f> emissionPoints = { Vector3f(0, 0, 0), Vector3f(0, 0, 0) };
emissionPoints[0] = Environment::shipState.position + Environment::shipState.rotation * Vector3f{ -0.9, 1.4 - 1.0, -8.5 + 16.0 };
emissionPoints[1] = Environment::shipState.position + Environment::shipState.rotation * Vector3f{ 0.9, 1.4 - 1.0, -8.5 + 16.0 };
sparkEmitterPtr->setEmissionPoints(emissionPoints);
//sparkEmitterPtr->setEmissionPoints({ /*0.5* */Environment::shipState.position });
//sparkEmitterPtr->setEmissionPoints({ Vector3f(0, 0, 0) });
std::cout << "Ship pos empo: " << Environment::shipState.position.transpose() << "\n";
}
if (Environment::shipState.velocity > 0.1f)
{
sparkEmitterPtr->setIsActive(true);
}
else
{
sparkEmitterPtr->setIsActive(false);
}
sparkEmitterPtr->update(static_cast<float>(delta));
auto latestRemotePlayers = networkClient->getRemotePlayers(); auto latestRemotePlayers = networkClient->getRemotePlayers();
std::chrono::system_clock::time_point nowRoundedWithDelay{ std::chrono::milliseconds(newTickCount - CLIENT_DELAY) }; std::chrono::system_clock::time_point nowRoundedWithDelay{ std::chrono::milliseconds(newTickCount - CLIENT_DELAY) };
@ -1607,7 +1611,7 @@ namespace ZL
for (const auto& p : projectiles) { for (const auto& p : projectiles) {
if (p && p->isActive()) { if (p && p->isActive()) {
Vector3f worldPos = p->getPosition(); Vector3f worldPos = p->getPosition();
p->projectileEmitter.setEmissionPoints({ worldPos }); p->projectileEmitter.resetEmissionPoints({ worldPos });
p->projectileEmitter.update(static_cast<float>(delta)); p->projectileEmitter.update(static_cast<float>(delta));
} }
} }

View File

@ -168,6 +168,18 @@ namespace ZL {
drawDataDirty = false; drawDataDirty = false;
} }
void SparkEmitter::prepareForDraw(bool withRotation) {
if (!configured) return;
prepareDrawData(withRotation);
if (!drawPositions.empty()) {
sparkQuad.data.PositionData = drawPositions;
sparkQuad.data.TexCoordData = drawTexCoords;
sparkQuad.RefreshVBO();
}
}
void SparkEmitter::draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight) void SparkEmitter::draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight)
{ {
draw(renderer, zoom, screenWidth, screenHeight, true); draw(renderer, zoom, screenWidth, screenHeight, true);
@ -186,35 +198,28 @@ namespace ZL {
throw std::runtime_error("Failed to load spark emitter config file 2!"); throw std::runtime_error("Failed to load spark emitter config file 2!");
} }
prepareDrawData(withRotation); //prepareDrawData(withRotation);
if (drawPositions.empty()) { if (drawPositions.empty()) {
return; return;
} }
/*
sparkQuad.data.PositionData = drawPositions; sparkQuad.data.PositionData = drawPositions;
sparkQuad.data.TexCoordData = drawTexCoords; sparkQuad.data.TexCoordData = drawTexCoords;
sparkQuad.RefreshVBO(); sparkQuad.RefreshVBO();
*/
renderer.shaderManager.PushShader(shaderProgramName); renderer.shaderManager.PushShader(shaderProgramName);
renderer.RenderUniform1i(textureUniformName, 0); renderer.RenderUniform1i(textureUniformName, 0);
renderer.SetMatrix();
//float aspectRatio = static_cast<float>(screenWidth) / static_cast<float>(screenHeight);
//renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, aspectRatio, Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
glBindTexture(GL_TEXTURE_2D, texture->getTexID()); glBindTexture(GL_TEXTURE_2D, texture->getTexID());
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendFunc(GL_SRC_ALPHA, GL_ONE);
renderer.PushMatrix(); //renderer.PushMatrix();
//renderer.LoadIdentity();
//renderer.TranslateMatrix({ 0, 0, -1.0f * zoom });
renderer.DrawVertexRenderStruct(sparkQuad); renderer.DrawVertexRenderStruct(sparkQuad);
//renderer.PopMatrix();
renderer.PopMatrix();
//renderer.PopProjectionMatrix();
glDisable(GL_BLEND); glDisable(GL_BLEND);
renderer.shaderManager.PopShader(); renderer.shaderManager.PopShader();
@ -229,9 +234,19 @@ namespace ZL {
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>( auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
currentTime - lastEmissionTime).count(); currentTime - lastEmissionTime).count();
if (isActive && elapsed >= emissionRate) { if (isActive && elapsed >= static_cast<long long>(emissionRate)) {
emit(); int emitCount = static_cast<int>(elapsed / emissionRate);
lastEmissionTime = currentTime; float elapsedF = static_cast<float>(elapsed);
for (int e = 0; e < emitCount; ++e) {
// e=0 — самая старая эмиссия, e=emitCount-1 — самая свежая
float ageMs = static_cast<float>(emitCount - 1 - e) * emissionRate;
// lerpT=0 → текущая позиция (новейшая), lerpT=1 → предыдущая (самая старая)
float lerpT = (elapsedF > 0.0f) ? min(ageMs / elapsedF, 1.0f) : 0.0f;
emit(ageMs, lerpT);
}
lastEmissionTime += std::chrono::milliseconds(
static_cast<long long>(emitCount * emissionRate));
drawDataDirty = true; drawDataDirty = true;
} }
@ -270,7 +285,7 @@ namespace ZL {
} }
} }
void SparkEmitter::emit() { void SparkEmitter::emit(float ageMs, float lerpT) {
if (!configured) { if (!configured) {
throw std::runtime_error("Failed to load spark emitter config file 4!"); throw std::runtime_error("Failed to load spark emitter config file 4!");
} }
@ -278,7 +293,30 @@ namespace ZL {
if (emissionPoints.empty()) return; if (emissionPoints.empty()) return;
bool emitted = false; bool emitted = false;
for (int i = 0; i < emissionPoints.size(); ++i) { auto applyAge = [](SparkParticle& particle, float age) {
if (age <= 0.0f) return;
particle.position(0) += particle.velocity(0) * age / 1000.0f;
particle.position(1) += particle.velocity(1) * age / 1000.0f;
particle.position(2) += particle.velocity(2) * age / 1000.0f;
particle.lifeTime = age;
if (particle.lifeTime >= particle.maxLifeTime) {
particle.active = false;
} else {
float lifeRatio = particle.lifeTime / particle.maxLifeTime;
particle.scale = 1.0f - lifeRatio * 0.8f;
}
};
// Вычисляем стартовую позицию с интерполяцией между prev и current
// lerpT=0 → текущая позиция (новейшая эмиссия), lerpT=1 → предыдущая (самая старая)
bool canInterp = (prevEmissionPoints.size() == emissionPoints.size());
for (int i = 0; i < (int)emissionPoints.size(); ++i) {
Vector3f birthPos = emissionPoints[i];
if (canInterp && lerpT > 0.0f) {
birthPos = emissionPoints[i] * (1.0f - lerpT) + prevEmissionPoints[i] * lerpT;
}
bool particleFound = false; bool particleFound = false;
for (auto& particle : particles) { for (auto& particle : particles) {
@ -286,8 +324,9 @@ namespace ZL {
initParticle(particle, i); initParticle(particle, i);
particle.active = true; particle.active = true;
particle.lifeTime = 0; particle.lifeTime = 0;
particle.position = emissionPoints[i]; particle.position = birthPos;
particle.emitterIndex = i; particle.emitterIndex = i;
applyAge(particle, ageMs);
particleFound = true; particleFound = true;
emitted = true; emitted = true;
break; break;
@ -296,11 +335,11 @@ namespace ZL {
if (!particleFound && !particles.empty()) { if (!particleFound && !particles.empty()) {
size_t oldestIndex = 0; size_t oldestIndex = 0;
float maxLifeTime = 0; float maxLifeRatio = 0;
for (size_t j = 0; j < particles.size(); ++j) { for (size_t j = 0; j < particles.size(); ++j) {
if (particles[j].lifeTime > maxLifeTime) { if (particles[j].lifeTime > maxLifeRatio) {
maxLifeTime = particles[j].lifeTime; maxLifeRatio = particles[j].lifeTime;
oldestIndex = j; oldestIndex = j;
} }
} }
@ -308,8 +347,9 @@ namespace ZL {
initParticle(particles[oldestIndex], i); initParticle(particles[oldestIndex], i);
particles[oldestIndex].active = true; particles[oldestIndex].active = true;
particles[oldestIndex].lifeTime = 0; particles[oldestIndex].lifeTime = 0;
particles[oldestIndex].position = emissionPoints[i]; particles[oldestIndex].position = birthPos;
particles[oldestIndex].emitterIndex = i; particles[oldestIndex].emitterIndex = i;
applyAge(particles[oldestIndex], ageMs);
emitted = true; emitted = true;
} }
} }
@ -320,6 +360,14 @@ namespace ZL {
} }
void SparkEmitter::setEmissionPoints(const std::vector<Vector3f>& positions) { void SparkEmitter::setEmissionPoints(const std::vector<Vector3f>& positions) {
prevEmissionPoints = emissionPoints;
emissionPoints = positions;
drawDataDirty = true;
}
void SparkEmitter::resetEmissionPoints(const std::vector<Vector3f>& positions)
{
prevEmissionPoints.clear();
emissionPoints = positions; emissionPoints = positions;
drawDataDirty = true; drawDataDirty = true;
} }
@ -487,8 +535,9 @@ namespace ZL {
std::cout << "Total emission points: " << emissionPoints.size() << std::endl; std::cout << "Total emission points: " << emissionPoints.size() << std::endl;
} }
else { else {
std::cerr << "Emission points parsed but empty" << std::endl; setEmissionPoints({});
throw std::runtime_error("Failed to load spark emitter config file 10!"); std::cout << "Emission points parsed but empty" << std::endl;
//throw std::runtime_error("Failed to load spark emitter config file 10!");
} }
} }
else { else {
@ -575,25 +624,6 @@ namespace ZL {
throw std::runtime_error("Failed to load spark emitter config file 18!"); throw std::runtime_error("Failed to load spark emitter config file 18!");
} }
std::cout << "Working with shaders 2" << std::endl;
/*
if (j.contains("vertexShader") && j.contains("fragmentShader")
&& j["vertexShader"].is_string() && j["fragmentShader"].is_string()) {
std::string v = j["vertexShader"].get<std::string>();
std::string f = j["fragmentShader"].get<std::string>();
std::cout << "Loading shaders - vertex: " << v << ", fragment: " << f << std::endl;
try {
renderer.shaderManager.AddShaderFromFiles(shaderProgramName, v, f, zipFile.c_str());
std::cout << "Shaders loaded successfully" << std::endl;
}
catch (const std::exception& e) {
std::cerr << "Shader load error: " << e.what() << std::endl;
throw std::runtime_error("Failed to load spark emitter config file 19!");
}
}*/
drawDataDirty = true; drawDataDirty = true;
configured = true; configured = true;
std::cout << "SparkEmitter configuration loaded successfully!" << std::endl; std::cout << "SparkEmitter configuration loaded successfully!" << std::endl;

View File

@ -26,6 +26,7 @@ namespace ZL {
private: private:
std::vector<SparkParticle> particles; std::vector<SparkParticle> particles;
std::vector<Vector3f> emissionPoints; std::vector<Vector3f> emissionPoints;
std::vector<Vector3f> prevEmissionPoints;
std::chrono::steady_clock::time_point lastEmissionTime; std::chrono::steady_clock::time_point lastEmissionTime;
float emissionRate; float emissionRate;
bool isActive; bool isActive;
@ -62,6 +63,7 @@ namespace ZL {
float rate = 100.0f); float rate = 100.0f);
void setEmissionPoints(const std::vector<Vector3f>& positions); void setEmissionPoints(const std::vector<Vector3f>& positions);
void resetEmissionPoints(const std::vector<Vector3f>& positions);
void setTexture(std::shared_ptr<Texture> tex); void setTexture(std::shared_ptr<Texture> tex);
void setEmissionRate(float rate) { emissionRate = rate; } void setEmissionRate(float rate) { emissionRate = rate; }
void setShaderProgramName(const std::string& name) { shaderProgramName = name; } void setShaderProgramName(const std::string& name) { shaderProgramName = name; }
@ -73,7 +75,10 @@ namespace ZL {
bool loadFromJsonFile(const std::string& path, Renderer& renderer, const std::string& zipFile = ""); bool loadFromJsonFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
void update(float deltaTimeMs); void update(float deltaTimeMs);
void emit(); void emit(float ageMs = 0.0f, float lerpT = 0.0f);
// Вызывать ДО draw() в начале кадра: готовит данные и загружает в VBO.
void prepareForDraw(bool withRotation = true);
void draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight); void draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight);
void draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight, bool withRotation); void draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight, bool withRotation);

View File

@ -381,7 +381,7 @@ namespace ZL {
glBindBuffer(GL_ARRAY_BUFFER, positionVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, positionVBO->getBuffer());
glBufferData(GL_ARRAY_BUFFER, data.PositionData.size() * 12, &data.PositionData[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, data.PositionData.size() * 12, &data.PositionData[0], GL_DYNAMIC_DRAW);
if (data.TexCoordData.size() > 0) if (data.TexCoordData.size() > 0)
{ {
@ -392,7 +392,7 @@ namespace ZL {
glBindBuffer(GL_ARRAY_BUFFER, texCoordVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, texCoordVBO->getBuffer());
glBufferData(GL_ARRAY_BUFFER, data.TexCoordData.size() * 8, &data.TexCoordData[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, data.TexCoordData.size() * 8, &data.TexCoordData[0], GL_DYNAMIC_DRAW);
} }
if (data.NormalData.size() > 0) if (data.NormalData.size() > 0)
@ -404,7 +404,7 @@ namespace ZL {
glBindBuffer(GL_ARRAY_BUFFER, normalVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, normalVBO->getBuffer());
glBufferData(GL_ARRAY_BUFFER, data.NormalData.size() * 12, &data.NormalData[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, data.NormalData.size() * 12, &data.NormalData[0], GL_DYNAMIC_DRAW);
} }
if (data.TangentData.size() > 0) if (data.TangentData.size() > 0)
@ -416,7 +416,7 @@ namespace ZL {
glBindBuffer(GL_ARRAY_BUFFER, tangentVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, tangentVBO->getBuffer());
glBufferData(GL_ARRAY_BUFFER, data.TangentData.size() * 12, &data.TangentData[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, data.TangentData.size() * 12, &data.TangentData[0], GL_DYNAMIC_DRAW);
} }
if (data.BinormalData.size() > 0) if (data.BinormalData.size() > 0)
@ -428,7 +428,7 @@ namespace ZL {
glBindBuffer(GL_ARRAY_BUFFER, binormalVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, binormalVBO->getBuffer());
glBufferData(GL_ARRAY_BUFFER, data.BinormalData.size() * 12, &data.BinormalData[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, data.BinormalData.size() * 12, &data.BinormalData[0], GL_DYNAMIC_DRAW);
} }
if (data.ColorData.size() > 0) if (data.ColorData.size() > 0)
@ -440,7 +440,7 @@ namespace ZL {
glBindBuffer(GL_ARRAY_BUFFER, colorVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, colorVBO->getBuffer());
glBufferData(GL_ARRAY_BUFFER, data.ColorData.size() * 12, &data.ColorData[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, data.ColorData.size() * 12, &data.ColorData[0], GL_DYNAMIC_DRAW);
} }
} }
@ -846,8 +846,25 @@ namespace ZL {
glVertexAttribPointer(shader->attribList[attribName], 3, GL_FLOAT, GL_FALSE, stride, pointer); glVertexAttribPointer(shader->attribList[attribName], 3, GL_FLOAT, GL_FALSE, stride, pointer);
} }
void Renderer::DisableVertexAttribArray(const std::string& attribName)
{
auto shader = shaderManager.GetCurrentShader();
auto it = shader->attribList.find(attribName);
if (it != shader->attribList.end())
glDisableVertexAttribArray(it->second);
}
void Renderer::DrawVertexRenderStruct(const VertexRenderStruct& VertexRenderStruct) void Renderer::DrawVertexRenderStruct(const VertexRenderStruct& VertexRenderStruct)
{ {
#ifndef EMSCRIPTEN
#ifndef __ANDROID__
if (VertexRenderStruct.vao) {
glBindVertexArray(VertexRenderStruct.vao->getBuffer());
shaderManager.EnableVertexAttribArrays();
}
#endif
#endif
static const std::string vNormal("vNormal"); static const std::string vNormal("vNormal");
static const std::string vTangent("vTangent"); static const std::string vTangent("vTangent");
static const std::string vBinormal("vBinormal"); static const std::string vBinormal("vBinormal");
@ -861,51 +878,46 @@ namespace ZL {
{ {
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.normalVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.normalVBO->getBuffer());
VertexAttribPointer3fv(vNormal, 0, NULL); VertexAttribPointer3fv(vNormal, 0, NULL);
//EnableVertexAttribArray(vNormal);
} }
else else
{ {
//DisableVertexAttribArray(vNormal); DisableVertexAttribArray(vNormal);
} }
if (VertexRenderStruct.data.TangentData.size() > 0) if (VertexRenderStruct.data.TangentData.size() > 0)
{ {
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.tangentVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.tangentVBO->getBuffer());
VertexAttribPointer3fv(vTangent, 0, NULL); VertexAttribPointer3fv(vTangent, 0, NULL);
//EnableVertexAttribArray(vTangent);
} }
else else
{ {
//DisableVertexAttribArray(vTangent); DisableVertexAttribArray(vTangent);
} }
if (VertexRenderStruct.data.BinormalData.size() > 0) if (VertexRenderStruct.data.BinormalData.size() > 0)
{ {
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.binormalVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.binormalVBO->getBuffer());
VertexAttribPointer3fv(vBinormal, 0, NULL); VertexAttribPointer3fv(vBinormal, 0, NULL);
//EnableVertexAttribArray(vBinormal);
} }
else else
{ {
//DisableVertexAttribArray(vBinormal); DisableVertexAttribArray(vBinormal);
} }
if (VertexRenderStruct.data.ColorData.size() > 0) if (VertexRenderStruct.data.ColorData.size() > 0)
{ {
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.colorVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.colorVBO->getBuffer());
VertexAttribPointer3fv(vColor, 0, NULL); VertexAttribPointer3fv(vColor, 0, NULL);
//EnableVertexAttribArray(vColor);
} }
else else
{ {
//DisableVertexAttribArray(vColor); DisableVertexAttribArray(vColor);
} }
if (VertexRenderStruct.data.TexCoordData.size() > 0) if (VertexRenderStruct.data.TexCoordData.size() > 0)
{ {
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.texCoordVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.texCoordVBO->getBuffer());
VertexAttribPointer2fv(vTexCoord, 0, NULL); VertexAttribPointer2fv(vTexCoord, 0, NULL);
//EnableVertexAttribArray(vTexCoord);
} }
else else
{ {
//DisableVertexAttribArray(vTexCoord); DisableVertexAttribArray(vTexCoord);
} }
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.positionVBO->getBuffer()); glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.positionVBO->getBuffer());

View File

@ -138,6 +138,8 @@ namespace ZL {
void VertexAttribPointer3fv(const std::string& attribName, int stride, const char* pointer); void VertexAttribPointer3fv(const std::string& attribName, int stride, const char* pointer);
void DisableVertexAttribArray(const std::string& attribName);
void DrawVertexRenderStruct(const VertexRenderStruct& VertexRenderStruct); void DrawVertexRenderStruct(const VertexRenderStruct& VertexRenderStruct);
}; };

View File

@ -200,7 +200,6 @@ namespace ZL {
{ {
glEnableVertexAttribArray(attrib.second); glEnableVertexAttribArray(attrib.second);
} }
} }
@ -232,6 +231,19 @@ namespace ZL {
} }
} }
void ShaderManager::EnableVertexAttribArrays()
{
if (shaderStack.size() != 0) {
auto& shaderResource = shaderResourceMap[shaderStack.top()];
auto& shaderAttribList = shaderResource->attribList;
for (auto& attrib : shaderAttribList)
{
glEnableVertexAttribArray(attrib.second);
}
}
}
std::shared_ptr <ShaderResource> ShaderManager::GetCurrentShader() { std::shared_ptr <ShaderResource> ShaderManager::GetCurrentShader() {
if (shaderStack.size() == 0) { if (shaderStack.size() == 0) {
throw std::runtime_error("Shader stack underflow!"); throw std::runtime_error("Shader stack underflow!");

View File

@ -42,6 +42,7 @@ namespace ZL {
void PushShader(const std::string& shaderName); void PushShader(const std::string& shaderName);
void PopShader(); void PopShader();
void EnableVertexAttribArrays();
std::shared_ptr<ShaderResource> GetCurrentShader(); std::shared_ptr<ShaderResource> GetCurrentShader();
}; };