Lights now are looking really good
* Draw lights beneath holes * Improve light particle * Light intensityvaries inversely with the square of the distance * Local player always have a minimum light in complete darkness * Creature names are behind lights now
This commit is contained in:
parent
d7a45311ed
commit
6e154f6b2c
|
@ -39,6 +39,8 @@ public:
|
|||
void paste(const ImagePtr& other);
|
||||
bool nextMipmap();
|
||||
|
||||
void setPixel(int x, int y, uint8 *pixel) { memcpy(&m_pixels[(y * m_size.width() + x) * m_bpp], pixel, m_bpp);}
|
||||
|
||||
std::vector<uint8>& getPixels() { return m_pixels; }
|
||||
uint8* getPixelData() { return &m_pixels[0]; }
|
||||
int getPixelCount() { return m_size.area(); }
|
||||
|
@ -46,7 +48,7 @@ public:
|
|||
int getWidth() { return m_size.width(); }
|
||||
int getHeight() { return m_size.height(); }
|
||||
int getBpp() { return m_bpp; }
|
||||
uint8* getPixel(int x, int y) { return &m_pixels[(y * m_size.width() + x) * 4]; }
|
||||
uint8* getPixel(int x, int y) { return &m_pixels[(y * m_size.width() + x) * m_bpp]; }
|
||||
|
||||
private:
|
||||
std::vector<uint8> m_pixels;
|
||||
|
|
|
@ -81,8 +81,19 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate, LightVie
|
|||
internalDrawOutfit(dest + animationOffset * scaleFactor, scaleFactor, animate, animate, m_direction);
|
||||
m_footStepDrawn = true;
|
||||
|
||||
if(lightView && m_light.intensity > 0)
|
||||
lightView->addLightSource(dest + (animationOffset + Point(16,16)) * scaleFactor, scaleFactor, m_light);
|
||||
if(lightView) {
|
||||
Light light = m_light;
|
||||
|
||||
// local player always have a minimum light in complete darkness
|
||||
if(isLocalPlayer() && (g_map.getLight().intensity < 40 || m_position.z > Otc::SEA_FLOOR)) {
|
||||
light.intensity = std::max<uint8>(light.intensity, 2);
|
||||
if(light.color == 0 || light.color > 215)
|
||||
light.color = 215;
|
||||
}
|
||||
|
||||
if(light.intensity > 0)
|
||||
lightView->addLightSource(dest + (animationOffset + Point(16,16)) * scaleFactor, scaleFactor, light);
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView)
|
||||
|
|
|
@ -36,29 +36,25 @@ LightView::LightView()
|
|||
|
||||
void LightView::generateLightBuble()
|
||||
{
|
||||
const int size = 256;
|
||||
uint8_t dest[size*size*4];
|
||||
m_lightRadius = 128;
|
||||
int circleDiameter = m_lightRadius * 2;
|
||||
ImagePtr lightImage = ImagePtr(new Image(Size(circleDiameter, circleDiameter)));
|
||||
|
||||
for(int x = 0; x < size; x++){
|
||||
for(int y = 0; y < size; y++){
|
||||
int norm = std::sqrt((size/2 - x)*(size/2 - x) + (size/2 - y)*(size/2 - y));
|
||||
float p = 128*norm/(size/2);
|
||||
for(int x = 0; x < circleDiameter; x++) {
|
||||
for(int y = 0; y < circleDiameter; y++) {
|
||||
float radius = std::sqrt((m_lightRadius - x)*(m_lightRadius - x) + (m_lightRadius - y)*(m_lightRadius - y));
|
||||
float intensity = std::max((m_lightRadius-radius)/(float)m_lightRadius, 0.0f);
|
||||
|
||||
float color = (p <= 128 ? 255 * (128-p)*(128-p)/(128*128) : 0);
|
||||
if(color < 0)
|
||||
color = 0;
|
||||
// light intensity varies inversely with the square of the distance
|
||||
intensity = intensity * intensity;
|
||||
uint8_t colorByte = intensity * 255;
|
||||
|
||||
int line = y;
|
||||
|
||||
dest[4*x + 4*size*line] = (uint8_t)color;
|
||||
dest[4*x + 4*size*line + 1] = (uint8_t)color;
|
||||
dest[4*x + 4*size*line + 2] = (uint8_t)color;
|
||||
dest[4*x + 4*size*line + 3] = 255;
|
||||
uint8_t pixel[4] = {colorByte,colorByte,colorByte,255};
|
||||
lightImage->setPixel(x, y, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
ImagePtr light = ImagePtr(new Image(Size(size,size), 4, dest));
|
||||
m_lightTexture = TexturePtr(new Texture(light, false));
|
||||
m_lightTexture = TexturePtr(new Texture(lightImage, true));
|
||||
m_lightTexture->setSmooth(true);
|
||||
}
|
||||
|
||||
|
@ -74,48 +70,66 @@ void LightView::setGlobalLight(const Light& light)
|
|||
|
||||
void LightView::addLightSource(const Point& center, float scaleFactor, const Light& light)
|
||||
{
|
||||
int radius = light.intensity * 64 * scaleFactor;
|
||||
int radius = light.intensity * m_lightRadius * scaleFactor * 0.25f;
|
||||
|
||||
Color color = Color::from8bit(light.color);
|
||||
float brightness = 0.8f + (light.intensity/8.0f)*0.2f;
|
||||
|
||||
color.setRed(color.rF() * brightness);
|
||||
color.setGreen(color.gF() * brightness);
|
||||
color.setBlue(color.bF() * brightness);
|
||||
|
||||
LightSource source;
|
||||
source.center = center;
|
||||
source.color = Color::from8bit(light.color);
|
||||
source.color = color;
|
||||
source.radius = radius;
|
||||
m_lightMap.push_back(source);
|
||||
}
|
||||
|
||||
void LightView::drawGlobalLight(const Light& light, const Size& size)
|
||||
void LightView::drawGlobalLight(const Light& light)
|
||||
{
|
||||
Color color = Color::from8bit(light.color);
|
||||
float factor = light.intensity / 256.0f;
|
||||
color.setRed(color.rF() * factor);
|
||||
color.setGreen(color.gF() * factor);
|
||||
color.setBlue(color.bF() * factor);
|
||||
color.setAlpha(1.0f);
|
||||
float brightness = light.intensity / 256.0f;
|
||||
color.setRed(color.rF() * brightness);
|
||||
color.setGreen(color.gF() * brightness);
|
||||
color.setBlue(color.bF() * brightness);
|
||||
g_painter->setColor(color);
|
||||
g_painter->drawFilledRect(Rect(0,0,size));
|
||||
g_painter->drawFilledRect(Rect(0,0,m_lightbuffer->getSize()));
|
||||
}
|
||||
|
||||
void LightView::drawLightSource(const Point& center, const Color& color, int radius)
|
||||
{
|
||||
Rect dest = Rect(center - Point(radius, radius), Size(radius*2,radius*2));
|
||||
g_painter->setColor(color);
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Add);
|
||||
g_painter->drawTexturedRect(dest, m_lightTexture);
|
||||
|
||||
// debug draw
|
||||
//g_painter->drawBoundingRect(dest);
|
||||
/*
|
||||
radius = 8;
|
||||
g_painter->setColor(Color::black);
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Replace);
|
||||
g_painter->drawBoundingRect(Rect(center - Point(radius, radius), Size(radius*2,radius*2)), 4);
|
||||
*/
|
||||
}
|
||||
|
||||
void LightView::draw(Size size)
|
||||
void LightView::resize(const Size& size)
|
||||
{
|
||||
m_lightbuffer->resize(size);
|
||||
}
|
||||
|
||||
void LightView::draw(const Rect& dest, const Rect& src)
|
||||
{
|
||||
g_painter->saveAndResetState();
|
||||
m_lightbuffer->bind();
|
||||
drawGlobalLight(m_globalLight, size);
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Replace);
|
||||
drawGlobalLight(m_globalLight);
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Add);
|
||||
for(const LightSource& source : m_lightMap)
|
||||
drawLightSource(source.center, source.color, source.radius);
|
||||
m_lightbuffer->release();
|
||||
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Light);
|
||||
m_lightbuffer->draw();
|
||||
g_painter->setCompositionMode(Painter::CompositionMode_Normal);
|
||||
m_lightbuffer->draw(dest, src);
|
||||
g_painter->restoreSavedState();
|
||||
}
|
||||
|
|
|
@ -41,14 +41,16 @@ public:
|
|||
void reset();
|
||||
void setGlobalLight(const Light& light);
|
||||
void addLightSource(const Point& center, float scaleFactor, const Light& light);
|
||||
void draw(Size size);
|
||||
void resize(const Size& size);
|
||||
void draw(const Rect& dest, const Rect& src);
|
||||
|
||||
private:
|
||||
void drawGlobalLight(const Light& light, const Size& size);
|
||||
void drawGlobalLight(const Light& light);
|
||||
void drawLightSource(const Point& center, const Color& color, int radius);
|
||||
void generateLightBuble();
|
||||
|
||||
TexturePtr m_lightTexture;
|
||||
int m_lightRadius;
|
||||
FrameBufferPtr m_lightbuffer;
|
||||
MapView* m_mapView;
|
||||
Light m_globalLight;
|
||||
|
|
|
@ -100,13 +100,14 @@ void MapView::draw(const Rect& rect)
|
|||
|
||||
if(m_drawLights) {
|
||||
m_lightView->reset();
|
||||
m_lightView->resize(m_framebuffer->getSize());
|
||||
|
||||
if(cameraPosition.z <= 7)
|
||||
m_lightView->setGlobalLight(g_map.getLight());
|
||||
else {
|
||||
Light undergroundLight;
|
||||
undergroundLight.color = 0;
|
||||
undergroundLight.intensity = 0;
|
||||
undergroundLight.color = 215;
|
||||
undergroundLight.intensity = 16;
|
||||
m_lightView->setGlobalLight(undergroundLight);
|
||||
}
|
||||
}
|
||||
|
@ -144,9 +145,6 @@ void MapView::draw(const Rect& rect)
|
|||
}
|
||||
}
|
||||
|
||||
if(m_drawLights && m_updateTilesPos == 0)
|
||||
m_lightView->draw(m_framebuffer->getSize());
|
||||
|
||||
m_framebuffer->release();
|
||||
|
||||
// generating mipmaps each frame can be slow in older cards
|
||||
|
@ -208,7 +206,13 @@ void MapView::draw(const Rect& rect)
|
|||
|
||||
creature->drawInformation(p, g_map.isCovered(pos, m_cachedFirstVisibleFloor), rect);
|
||||
}
|
||||
}
|
||||
|
||||
// lights are drawn after names and before texts
|
||||
if(m_drawLights)
|
||||
m_lightView->draw(rect, srcRect);
|
||||
|
||||
if(m_viewMode == NEAR_VIEW && m_drawTexts) {
|
||||
for(const StaticTextPtr& staticText : g_map.getStaticTexts()) {
|
||||
Position pos = staticText->getPosition();
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ struct MarketData {
|
|||
};
|
||||
|
||||
struct Light {
|
||||
Light() { intensity = 0; color = 215; }
|
||||
uint8 intensity;
|
||||
uint8 color;
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "localplayer.h"
|
||||
#include "effect.h"
|
||||
#include "protocolgame.h"
|
||||
#include "lightview.h"
|
||||
#include <framework/graphics/fontmanager.h>
|
||||
|
||||
Tile::Tile(const Position& position) :
|
||||
|
@ -92,7 +93,7 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *
|
|||
continue;
|
||||
const TilePtr& tile = g_map.getTile(m_position.translated(x,y));
|
||||
if(tile)
|
||||
tile->draw(dest + Point(x*Otc::TILE_PIXELS, y*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, topRedrawFlags, lightView);
|
||||
tile->draw(dest + Point(x*Otc::TILE_PIXELS, y*Otc::TILE_PIXELS)*scaleFactor, scaleFactor, topRedrawFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +134,13 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw translucent light (for tiles beneath holes)
|
||||
if(hasTranslucentLight() && lightView) {
|
||||
Light light;
|
||||
light.intensity = 2;
|
||||
lightView->addLightSource(dest + Point(16,16) * scaleFactor, scaleFactor, light);
|
||||
}
|
||||
}
|
||||
|
||||
void Tile::clean()
|
||||
|
@ -213,6 +221,9 @@ void Tile::addThing(const ThingPtr& thing, int stackPos)
|
|||
|
||||
thing->setPosition(m_position);
|
||||
thing->onAppear();
|
||||
|
||||
if(thing->isTranslucent())
|
||||
checkTranslucentLight();
|
||||
}
|
||||
|
||||
bool Tile::removeThing(ThingPtr thing)
|
||||
|
@ -239,6 +250,9 @@ bool Tile::removeThing(ThingPtr thing)
|
|||
|
||||
thing->onDisappear();
|
||||
|
||||
if(thing->isTranslucent())
|
||||
checkTranslucentLight();
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
|
@ -567,7 +581,7 @@ bool Tile::limitsFloorsView()
|
|||
|
||||
bool Tile::canErase()
|
||||
{
|
||||
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty();
|
||||
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0;
|
||||
}
|
||||
|
||||
bool Tile::hasElevation(int elevation)
|
||||
|
@ -578,3 +592,30 @@ bool Tile::hasElevation(int elevation)
|
|||
count++;
|
||||
return count >= elevation;
|
||||
}
|
||||
|
||||
void Tile::checkTranslucentLight()
|
||||
{
|
||||
if(m_position.z < Otc::SEA_FLOOR)
|
||||
return;
|
||||
|
||||
Position downPos = m_position;
|
||||
if(!downPos.down())
|
||||
return;
|
||||
|
||||
TilePtr tile = g_map.getOrCreateTile(downPos);
|
||||
if(!tile)
|
||||
return;
|
||||
|
||||
bool translucent = false;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isTranslucent() || thing->hasLensHelp()) {
|
||||
translucent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(translucent)
|
||||
tile->m_flags = tile->m_flags | TILESTATE_TRANSLUECENT_LIGHT;
|
||||
else
|
||||
tile->m_flags = tile->m_flags & ~TILESTATE_TRANSLUECENT_LIGHT;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ enum tileflags_t
|
|||
TILESTATE_MAILBOX = 1 << 19,
|
||||
TILESTATE_TRASHHOLDER = 1 << 20,
|
||||
TILESTATE_BED = 1 << 21,
|
||||
TILESTATE_DEPOT = 1 << 22
|
||||
TILESTATE_DEPOT = 1 << 22,
|
||||
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23
|
||||
};
|
||||
|
||||
#pragma pack(push,1) // disable memory alignment
|
||||
|
@ -101,6 +102,7 @@ public:
|
|||
bool isClickable();
|
||||
bool isEmpty();
|
||||
bool isDrawable();
|
||||
bool hasTranslucentLight() { return m_flags & TILESTATE_TRANSLUECENT_LIGHT; }
|
||||
bool mustHookSouth();
|
||||
bool mustHookEast();
|
||||
bool hasCreature();
|
||||
|
@ -118,6 +120,8 @@ public:
|
|||
TilePtr asTile() { return static_self_cast<Tile>(); }
|
||||
|
||||
private:
|
||||
void checkTranslucentLight();
|
||||
|
||||
stdext::packed_vector<CreaturePtr> m_walkingCreatures;
|
||||
stdext::packed_vector<EffectPtr> m_effects; // leave this outside m_things because it has no stackpos.
|
||||
stdext::packed_vector<ThingPtr> m_things;
|
||||
|
|
Loading…
Reference in New Issue