Skip to content

Commit

Permalink
fix #4164
Browse files Browse the repository at this point in the history
shield{Good,Bad}Color are RGBA float4's now
  • Loading branch information
rt committed Jun 21, 2017
1 parent 87283cc commit 216f8bf
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 138 deletions.
2 changes: 2 additions & 0 deletions rts/Lua/LuaWeaponDefs.cpp
Expand Up @@ -552,9 +552,11 @@ static bool InitParamMap()
ADD_FLOAT("shieldGoodColorR", wd.shieldGoodColor.x);
ADD_FLOAT("shieldGoodColorG", wd.shieldGoodColor.y);
ADD_FLOAT("shieldGoodColorB", wd.shieldGoodColor.z);
ADD_FLOAT("shieldGoodColorA", wd.shieldGoodColor.w);
ADD_FLOAT("shieldBadColorR", wd.shieldBadColor.x);
ADD_FLOAT("shieldBadColorG", wd.shieldBadColor.y);
ADD_FLOAT("shieldBadColorB", wd.shieldBadColor.z);
ADD_FLOAT("shieldBadColorA", wd.shieldBadColor.w);
ADD_FLOAT("shieldAlpha", wd.shieldAlpha);

ADD_INT("shieldInterceptType", wd.shieldInterceptType);
Expand Down
95 changes: 45 additions & 50 deletions rts/Rendering/Env/Particles/Classes/RepulseGfx.cpp
Expand Up @@ -13,50 +13,51 @@ CR_BIND_DERIVED_POOL(CRepulseGfx, CProjectile, , projMemPool.alloc, projMemPool.

CR_REG_METADATA(CRepulseGfx,(
CR_MEMBER(repulsed),
CR_MEMBER(sqMaxDist),
CR_MEMBER(sqMaxOwnerDist),
CR_MEMBER(age),
CR_MEMBER(color),
CR_MEMBER(difs)
CR_MEMBER(vertexDists)
))


CRepulseGfx::CRepulseGfx(CUnit* owner, CProjectile* repulsed, float maxDist, const float3& color):
CProjectile(repulsed? repulsed->pos: ZeroVector, repulsed? repulsed->speed: ZeroVector, owner, false, false, false),
repulsed(repulsed),
sqMaxDist((maxDist * maxDist) + 100),
CRepulseGfx::CRepulseGfx(CUnit* owner, CProjectile* repulsee, float maxOwnerDist, const float4& gfxColor):
CProjectile((repulsee != nullptr)? repulsed->pos: ZeroVector, (repulsee != nullptr)? repulsee->speed: ZeroVector, owner, false, false, false),
repulsed(repulsee),
age(0),
color(color)
sqMaxOwnerDist((maxOwnerDist * maxOwnerDist) + 100.0f),
color(gfxColor)
{
if (repulsed) {
if (repulsed != nullptr)
AddDeathDependence(repulsed, DEPENDENCE_REPULSE);
}

checkCol = false;
useAirLos = true;

SetRadiusAndHeight(maxDist, 0.0f);
SetRadiusAndHeight(maxOwnerDist, 0.0f);

for (int y = 0; y < 5; ++y) {
float yp = (y / 4.0f - 0.5f);

for (int x = 0; x < 5; ++x) {
float xp = (x / 4.0f - 0.5f);
float d = 0;
if (xp != 0 || yp != 0) {

if (xp != 0 || yp != 0)
d = fastmath::apxsqrt2(xp * xp + yp * yp);
}
difs[y * 5 + x] = (1 - fastmath::cos(d * 2)) * 20;

vertexDists[y * 5 + x] = (1.0f - fastmath::cos(d * 2.0f)) * 20.0f;
}
}
}


void CRepulseGfx::DependentDied(CObject* o)
{
if (o == repulsed) {
repulsed = nullptr;
deleteMe = true;
}
if (o != repulsed)
return;

repulsed = nullptr;
deleteMe = true;
}

void CRepulseGfx::Draw(CVertexArray* va)
Expand All @@ -77,12 +78,14 @@ void CRepulseGfx::Draw(CVertexArray* va)

float drawsize = 10.0f;
float alpha = std::min(255.0f, age * 10.0f);

unsigned char col[4] = {
(unsigned char) (color.x * alpha),
(unsigned char) (color.y * alpha),
(unsigned char) (color.z * alpha),
(unsigned char) (0.2f * alpha),
(unsigned char) (color.x * alpha ),
(unsigned char) (color.y * alpha ),
(unsigned char) (color.z * alpha ),
(unsigned char) (color.w * alpha * 0.2f),

This comment has been minimized.

Copy link
@sprunk

sprunk Jun 30, 2017

Contributor

The 0.2 should probably be a default of some sort? Most games probably don't have any value set for alpha while someone might want a thicker shield.

This comment has been minimized.

Copy link
@rtri

rtri Jun 30, 2017

Contributor

This bit of code only renders the repulse-effect, not shields.

};
constexpr unsigned char col2[4] = {0, 0, 0, 0};

xdirDS = xdir * drawsize;
ydirDS = ydir * drawsize;
Expand All @@ -93,8 +96,8 @@ void CRepulseGfx::Draw(CVertexArray* va)
const float txs = et->xend - et->xstart;
const float tys = et->yend - et->ystart;

static const int loopCountY = 4;
static const int loopCountX = 4;
static constexpr int loopCountY = 4;
static constexpr int loopCountX = 4;

va->EnlargeArrays(loopCountY * loopCountX * 4 + 16, 0, VA_SIZE_TC);

Expand All @@ -106,60 +109,52 @@ void CRepulseGfx::Draw(CVertexArray* va)
const float dx = x - 2.00f;
const float rx = x * 0.25f;

va->AddVertexQTC(pos + xdirDS * (dx + 0) + ydirDS * (dy + 0) + zdir * difs[(y ) * 5 + x ], txo + (ry ) * txs, tyo + (rx ) * tys, col);
va->AddVertexQTC(pos + xdirDS * (dx + 0) + ydirDS * (dy + 1) + zdir * difs[(y + 1) * 5 + x ], txo + (ry + 0.25f) * txs, tyo + (rx ) * tys, col);
va->AddVertexQTC(pos + xdirDS * (dx + 1) + ydirDS * (dy + 1) + zdir * difs[(y + 1) * 5 + x + 1], txo + (ry + 0.25f) * txs, tyo + (rx + 0.25f) * tys, col);
va->AddVertexQTC(pos + xdirDS * (dx + 1) + ydirDS * (dy + 0) + zdir * difs[(y ) * 5 + x + 1], txo + (ry ) * txs, tyo + (rx + 0.25f) * tys, col);
va->AddVertexQTC(pos + xdirDS * (dx + 0) + ydirDS * (dy + 0) + zdir * vertexDists[(y ) * 5 + x ], txo + (ry ) * txs, tyo + (rx ) * tys, col);
va->AddVertexQTC(pos + xdirDS * (dx + 0) + ydirDS * (dy + 1) + zdir * vertexDists[(y + 1) * 5 + x ], txo + (ry + 0.25f) * txs, tyo + (rx ) * tys, col);
va->AddVertexQTC(pos + xdirDS * (dx + 1) + ydirDS * (dy + 1) + zdir * vertexDists[(y + 1) * 5 + x + 1], txo + (ry + 0.25f) * txs, tyo + (rx + 0.25f) * tys, col);
va->AddVertexQTC(pos + xdirDS * (dx + 1) + ydirDS * (dy + 0) + zdir * vertexDists[(y ) * 5 + x + 1], txo + (ry ) * txs, tyo + (rx + 0.25f) * tys, col);
}
}

drawsize = 7.0f;
alpha = std::min(10.0f, age / 2.0f);
col[0] = (unsigned char) (color.x * alpha);
col[1] = (unsigned char) (color.y * alpha);
col[2] = (unsigned char) (color.z * alpha);
col[3] = (unsigned char) (alpha * 0.4f);

col[0] = (unsigned char) (color.x * alpha );
col[1] = (unsigned char) (color.y * alpha );
col[2] = (unsigned char) (color.z * alpha );
col[3] = (unsigned char) (color.w * alpha * 0.4f);

const AtlasedTexture* ct = projectileDrawer->repulsegfxtex;
const float tx = (ct->xend + ct->xstart) * 0.5f;
const float ty = (ct->yend + ct->ystart) * 0.5f;

static const unsigned char col2[4] = {0, 0, 0, 0};

xdirDS = xdir * drawsize;
ydirDS = ydir * drawsize;

va->AddVertexQTC(owner->pos + (-xdir + ydir) * drawsize * 0.2f, tx, ty, col2);
va->AddVertexQTC(owner->pos + ( xdir + ydir) * drawsize * 0.2f, tx, ty, col2);
va->AddVertexQTC( pos + xdirDS + ydirDS + zdir * difs[6], tx, ty, col);
va->AddVertexQTC( pos - xdirDS + ydirDS + zdir * difs[6], tx, ty, col);
va->AddVertexQTC( pos + xdirDS + ydirDS + zdir * vertexDists[6], tx, ty, col );
va->AddVertexQTC( pos - xdirDS + ydirDS + zdir * vertexDists[6], tx, ty, col );

va->AddVertexQTC(owner->pos + (-xdir - ydir) * drawsize * 0.2f, tx, ty, col2);
va->AddVertexQTC(owner->pos + ( xdir - ydir) * drawsize * 0.2f, tx, ty, col2);
va->AddVertexQTC( pos + xdirDS - ydirDS + zdir * difs[6], tx, ty, col);
va->AddVertexQTC( pos - xdirDS - ydirDS + zdir * difs[6], tx, ty, col);
va->AddVertexQTC( pos + xdirDS - ydirDS + zdir * vertexDists[6], tx, ty, col );
va->AddVertexQTC( pos - xdirDS - ydirDS + zdir * vertexDists[6], tx, ty, col );

va->AddVertexQTC(owner->pos + (xdir - ydir) * drawsize * 0.2f, tx, ty, col2);
va->AddVertexQTC(owner->pos + (xdir + ydir) * drawsize * 0.2f, tx, ty, col2);
va->AddVertexQTC( pos + xdirDS + ydirDS + zdir * difs[6], tx, ty, col);
va->AddVertexQTC( pos + xdirDS - ydirDS + zdir * difs[6], tx, ty, col);
va->AddVertexQTC( pos + xdirDS + ydirDS + zdir * vertexDists[6], tx, ty, col );
va->AddVertexQTC( pos + xdirDS - ydirDS + zdir * vertexDists[6], tx, ty, col );

va->AddVertexQTC(owner->pos + (-xdir - ydir) * drawsize * 0.2f, tx, ty, col2);
va->AddVertexQTC(owner->pos + (-xdir + ydir) * drawsize * 0.2f, tx, ty, col2);
va->AddVertexQTC( pos - xdirDS + ydirDS + zdir * difs[6], tx, ty, col);
va->AddVertexQTC( pos - xdirDS - ydirDS + zdir * difs[6], tx, ty, col);
va->AddVertexQTC( pos - xdirDS + ydirDS + zdir * vertexDists[6], tx, ty, col );
va->AddVertexQTC( pos - xdirDS - ydirDS + zdir * vertexDists[6], tx, ty, col );
}

void CRepulseGfx::Update()
{
age++;

if (repulsed && owner() && (repulsed->pos - owner()->pos).SqLength() > sqMaxDist) {
deleteMe = true;
}
age += 1;
deleteMe |= (repulsed != nullptr && owner() != nullptr && (repulsed->pos - owner()->pos).SqLength() > sqMaxOwnerDist);
}

int CRepulseGfx::GetProjectilesCount() const
{
return 20;
}
16 changes: 9 additions & 7 deletions rts/Rendering/Env/Particles/Classes/RepulseGfx.h
Expand Up @@ -14,25 +14,27 @@ class CRepulseGfx : public CProjectile
CRepulseGfx() { }
CRepulseGfx(
CUnit* owner,
CProjectile* repulsed,
float maxDist,
const float3& color
CProjectile* repulsee,
float maxOwnerDist,
const float4& gfxColor
);

void Draw(CVertexArray* va) override;
void Update() override;

int GetProjectilesCount() const override;
int GetProjectilesCount() const override { return 20; }

void DependentDied(CObject* o) override;

private:
CProjectile* repulsed;
float sqMaxDist;

int age;
float3 color;

float difs[25];
float sqMaxOwnerDist;
float vertexDists[25];

float4 color;
};

#endif // REPULSE_GFX_H
13 changes: 4 additions & 9 deletions rts/Rendering/Env/Particles/Classes/ShieldSegmentProjectile.cpp
Expand Up @@ -122,7 +122,7 @@ bool ShieldSegmentCollection::AllowDrawing()

//FIXME if Lua wants to draw the shield itself, we should draw all GL_QUADS in the `va` vertexArray first.
// but doing so for each shield might reduce the performance.
// so might use a branch-predicion? -> save last return value and if it is true draw `va` before calling eventHandler.DrawShield() ??FIXME
// so might use a branch-predicion? -> save last return value and if it is true draw `va` before calling eventHandler.DrawShield()
if (eventHandler.DrawShield(shield->owner, shield))
return allowDrawing;

Expand All @@ -142,9 +142,9 @@ void ShieldSegmentCollection::UpdateColor()
const WeaponDef* shieldDef = shield->weaponDef;

// lerp between badColor and goodColor based on shield's current power
const float colorMix = std::min(1.0f, shield->GetCurPower() / std::max(1.0f, shieldDef->shieldPower));
const float relPower = shield->GetCurPower() / std::max(1.0f, shieldDef->shieldPower);
const float lrpColor = std::min(1.0f, relPower);

const float3 colorf = mix(shieldDef->shieldBadColor, shieldDef->shieldGoodColor, colorMix);
float alpha = shieldDef->visibleShield * shieldDef->shieldAlpha;

if (shield->GetHitFrames() > 0 && shieldDef->visibleShieldHitFrames > 0) {
Expand All @@ -154,12 +154,7 @@ void ShieldSegmentCollection::UpdateColor()
alpha = std::min(alpha, 1.0f);
}

color = SColor(
colorf.x * alpha,
colorf.y * alpha,
colorf.z * alpha,
alpha
);
color = SColor(mix(shieldDef->shieldBadColor, shieldDef->shieldGoodColor, lrpColor) * alpha);
}


Expand Down
12 changes: 4 additions & 8 deletions rts/Rendering/Env/Particles/Classes/SmokeProjectile2.cpp
Expand Up @@ -67,9 +67,8 @@ CSmokeProjectile2::CSmokeProjectile2(
ageSpeed = 1 / ttl;
checkCol = false;
castShadow = true;
if ((pos.y - CGround::GetApproximateHeight(pos.x, pos.z, false)) > 10) {
useAirLos = true;
}
useAirLos |= ((pos.y - CGround::GetApproximateHeight(pos.x, pos.z, false)) > 10.0f);

glowFalloff = 4.5f + guRNG.NextFloat() * 6;
textureNum = (int)(guRNG.NextInt(projectileDrawer->smoketex.size()));
}
Expand All @@ -78,11 +77,8 @@ CSmokeProjectile2::CSmokeProjectile2(

void CSmokeProjectile2::Init(const CUnit* owner, const float3& offset)
{
if (offset.y - CGround::GetApproximateHeight(offset.x, offset.z, false) > 10)
useAirLos = true;

if (!owner)
alwaysVisible = true;
useAirLos |= (offset.y - CGround::GetApproximateHeight(offset.x, offset.z, false) > 10.0f);
alwaysVisible |= (owner == nullptr);

wantedPos += offset;

Expand Down
2 changes: 1 addition & 1 deletion rts/Rendering/ShadowHandler.cpp
Expand Up @@ -421,7 +421,7 @@ static CMatrix44f ComposeLightMatrix(const ISkyLight* light)
CMatrix44f lightMatrix;

// sun direction is in world-space, invert it
lightMatrix.SetZ(-(light->GetLightDir()));
lightMatrix.SetZ(-float3(light->GetLightDir()));
lightMatrix.SetX(((lightMatrix.GetZ()).cross( UpVector )).ANormalize());
lightMatrix.SetY(((lightMatrix.GetX()).cross(lightMatrix.GetZ())).ANormalize());

Expand Down
65 changes: 29 additions & 36 deletions rts/Sim/Weapons/PlasmaRepulser.cpp
Expand Up @@ -143,59 +143,52 @@ bool CPlasmaRepulser::IncomingProjectile(CWeaponProjectile* p, const float3& hit

if (weaponDef->shieldRepulser) {
// bounce the projectile
const int type = p->ShieldRepulse(weaponMuzzlePos,
weaponDef->shieldForce,
weaponDef->shieldMaxSpeed);

if (type == 0) {
return false;
} else if (type == 1) {
owner->UseEnergy(weaponDef->shieldEnergyUse);

if (weaponDef->shieldPower != 0) {
curPower -= shieldDamage;
}
} else {
//FIXME why do all weapons except LASERs do only (1 / GAME_SPEED) damage???
// because they go inside and take time to get pushed back
// during that time they deal damage every frame
// so in total they do their nominal damage each second
// on the other hand lasers get insta-bounced in 1 frame
// regardless of shield pushing power
owner->UseEnergy(weaponDef->shieldEnergyUse / GAME_SPEED);

curPower -= ((shieldDamage / GAME_SPEED) * (weaponDef->shieldPower != 0.0f));
switch (p->ShieldRepulse(weaponMuzzlePos, weaponDef->shieldForce, weaponDef->shieldMaxSpeed)) {
case 0: { return false; } break;
case 1: {
owner->UseEnergy(weaponDef->shieldEnergyUse);

curPower -= (shieldDamage * (weaponDef->shieldPower != 0.0f));
} break;
default: {
// NOTE:
// all weapons except Lasers do only (1 / GAME_SPEED) damage
// (Lasers are insta-bounced, others spend time "inside" the
// shield dealing damage every frame)
owner->UseEnergy(weaponDef->shieldEnergyUse / GAME_SPEED);

curPower -= ((shieldDamage / GAME_SPEED) * (weaponDef->shieldPower != 0.0f));
} break;
}

if (spring::VectorInsertUnique(repulsedProjectiles, p, true)) {
// projectile was not repulsed before
AddDeathDependence(p, DEPENDENCE_REPULSED);

if (weaponDef->visibleShieldRepulse) {
const float colorMix = std::min(1.0f, curPower / std::max(1.0f, weaponDef->shieldPower));
const float3 color =
(weaponDef->shieldGoodColor * colorMix) +
(weaponDef->shieldBadColor * (1.0f - colorMix));
const float relPower = curPower / std::max(1.0f, weaponDef->shieldPower);
const float lrpColor = std::min(1.0f, relPower);

projMemPool.alloc<CRepulseGfx>(owner, p, radius, color);
projMemPool.alloc<CRepulseGfx>(owner, p, radius, mix(weaponDef->shieldBadColor, weaponDef->shieldGoodColor, lrpColor));
}
}

if (defHitFrames > 0)
hitFrames = defHitFrames;

} else {
// kill the projectile
if (owner->UseEnergy(weaponDef->shieldEnergyUse)) {
curPower -= (shieldDamage * (weaponDef->shieldPower != 0.0f));
return false;
}

p->Collision();
// kill the projectile
if (owner->UseEnergy(weaponDef->shieldEnergyUse)) {
curPower -= (shieldDamage * (weaponDef->shieldPower != 0.0f));

if (defHitFrames > 0)
hitFrames = defHitFrames;
p->Collision();

return true;
}
if (defHitFrames > 0)
hitFrames = defHitFrames;

return true;
}

return false;
Expand Down
8 changes: 4 additions & 4 deletions rts/Sim/Weapons/WeaponDef.cpp
Expand Up @@ -189,10 +189,10 @@ WEAPONTAG(bool, visibleShieldRepulse).externalName("shield.visibleRepulse").fall
.defaultValue(false).description("Is the (hard-coded) repulse effect rendered or not?");
WEAPONTAG(int, visibleShieldHitFrames).externalName("shield.visibleHitFrames").fallbackName("visibleShieldHitFrames")
.defaultValue(0).description("The number of frames a shield becomes visible for when hit.");
WEAPONTAG(float3, shieldBadColor).externalName("shield.badColor").fallbackName("shieldBadColor")
.defaultValue(float3(1.0f, 0.5f, 0.5f)).description("The RGB colour the shield transitions to as its hit-points are reduced towards 0.");
WEAPONTAG(float3, shieldGoodColor).externalName("shield.goodColor").fallbackName("shieldGoodColor")
.defaultValue(float3(0.5f, 0.5f, 1.0f)).description("The RGB colour the shield transitions to as its hit-points are regenerated towards its maximum power.");
WEAPONTAG(float4, shieldBadColor).externalName("shield.badColor").fallbackName("shieldBadColor")
.defaultValue(float4(1.0f, 0.5f, 0.5f, 1.0f)).description("The RGBA colour the shield transitions to as its hit-points are reduced towards 0.");
WEAPONTAG(float4, shieldGoodColor).externalName("shield.goodColor").fallbackName("shieldGoodColor")
.defaultValue(float4(0.5f, 0.5f, 1.0f, 1.0f)).description("The RGBA colour the shield transitions to as its hit-points are regenerated towards its maximum power.");
WEAPONTAG(float, shieldAlpha).externalName("shield.alpha").fallbackName("shieldAlpha")
.defaultValue(0.2f).description("The alpha transparency of the shield whilst it is visible.");
WEAPONTAG(std::string, shieldArmorTypeName).externalName("shield.armorType").fallbackName("shieldArmorType")
Expand Down

0 comments on commit 216f8bf

Please sign in to comment.