rendermax: added adv mode lights also more proc-expensive diffuse mode.

develop
Warmist 2014-02-14 11:50:12 +02:00
parent b5b01ea02b
commit 50963c73fa
4 changed files with 113 additions and 17 deletions

@ -124,6 +124,7 @@ void lightingEngineViewscreen::reinit()
ocupancy.resize(size);
lights.resize(size);
}
void plotCircle(int xm, int ym, int r,const std::function<void(int,int)>& setPixel)
{
int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */
@ -163,7 +164,7 @@ void plotLine(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf
{
power=setPixel(power,rdx,rdy,x0,y0);
if(power.dot(power)<0.00001f)
return;
return ;
}
if (x0==x1 && y0==y1) break;
e2 = 2*err;
@ -171,8 +172,44 @@ void plotLine(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf
if (e2 >= dy) { err += dy; x0 += sx; rdx=sx;} /* e_xy+e_x > 0 */
if (e2 <= dx) { err += dx; y0 += sy; rdy=sy;} /* e_xy+e_y < 0 */
}
return ;
}
void plotLineDiffuse(int x0, int y0, int x1, int y1,rgbf power,int num_diffuse,const std::function<rgbf(rgbf,int,int,int,int)>& setPixel,bool skip_hack=false)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
int dsq=dx*dx+dy*dy;
int err = dx+dy, e2; /* error value e_xy */
int rdx=0;
int rdy=0;
for(;;){ /* loop */
if(rdx!=0 || rdy!=0 || skip_hack) //dirty hack to skip occlusion on the first tile.
{
power=setPixel(power,rdx,rdy,x0,y0);
if(power.dot(power)<0.00001f)
return ;
}
if (x0==x1 && y0==y1) break;
e2 = 2*err;
rdx=rdy=0;
if (e2 >= dy) { err += dy; x0 += sx; rdx=sx;} /* e_xy+e_x > 0 */
if (e2 <= dx) { err += dx; y0 += sy; rdy=sy;} /* e_xy+e_y < 0 */
if(num_diffuse>0 && dsq/4<(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0))//reached center?
{
const float betta=0.25;
int nx=y1-y0; //right angle
int ny=x1-x0;
if((nx*nx+ny*ny)*betta*betta>2)
{
plotLineDiffuse(x0,y0,x0+nx*betta,y0+ny*betta,power,num_diffuse-1,setPixel,true);
plotLineDiffuse(x0,y0,x0-nx*betta,y0-ny*betta,power,num_diffuse-1,setPixel,true);
}
}
}
return ;
}
void plotLineAA(int x0, int y0, int x1, int y1,rgbf power,const std::function<rgbf(rgbf,int,int,int,int)>& setPixelAA)
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
@ -269,7 +306,14 @@ void lightingEngineViewscreen::updateWindow()
myRenderer->invalidate();
return;
}
bool isAdventure=(*df::global::gametype==df::game_type::ADVENTURE_ARENA)||
(*df::global::gametype==df::game_type::ADVENTURE_MAIN);
if(isAdventure)
{
fixAdvMode(adv_mode);
}
if(doDebug)
std::swap(ocupancy,myRenderer->lightGrid);
else
@ -278,9 +322,47 @@ void lightingEngineViewscreen::updateWindow()
myRenderer->invalidateRect(vp.first.x,vp.first.y,vp.second.x-vp.first.x,vp.second.y-vp.first.y);
}
static size_t max_list_size = 100000; // Avoid iterating over huge lists
void lightingEngineViewscreen::preRender()
{
}
void lightingEngineViewscreen::fixAdvMode(int mode)
{
MapExtras::MapCache mc;
const rgbf dim(levelDim,levelDim,levelDim);
rect2d vp=getMapViewport();
int window_x=*df::global::window_x;
int window_y=*df::global::window_y;
int window_z=*df::global::window_z;
coord2d vpSize=rect_size(vp);
//mode 0-> make dark non-visible parts
if(mode==0)
{
for(int x=vp.first.x;x<vp.second.x;x++)
for(int y=vp.first.y;y<vp.second.y;y++)
{
df::tile_designation d=mc.designationAt(DFCoord(window_x+x,window_y+y,window_z));
if(d.bits.pile!=1)
{
lightMap[getIndex(x,y)]=dim;
}
}
}
//mode 1-> make everything visible, let the lighting hide stuff
else if(mode==1)
{
for(int x=vp.first.x;x<vp.second.x;x++)
for(int y=vp.first.y;y<vp.second.y;y++)
{
df::tile_designation d=mc.designationAt(DFCoord(window_x+x,window_y+y,window_z));
d.bits.dig=df::tile_dig_designation::Default;//TODO add union and flag there
d.bits.hidden=0;
d.bits.pile = 1;
mc.setDesignationAt(DFCoord(window_x+x,window_y+y,window_z),d);
}
}
}
void lightSource::combine(const lightSource& other)
{
power=blend(power,other.power);
@ -583,7 +665,7 @@ void lightingEngineViewscreen::doOcupancyAndLights()
df::tiletype type = b->tiletypeAt(gpos);
df::tile_designation d = b->DesignationAt(gpos);
if(d.bits.hidden)
if(d.bits.hidden )
{
curCell=rgbf(0,0,0);
continue; // do not process hidden stuff, TODO other hidden stuff
@ -947,6 +1029,8 @@ int lightingEngineViewscreen::parseSpecial(lua_State* L)
GETLUANUMBER(engine->levelDim,levelDim);
GETLUANUMBER(engine->dayHour,dayHour);
GETLUANUMBER(engine->daySpeed,daySpeed);
GETLUANUMBER(engine->num_diffuse,diffusionCount);
GETLUANUMBER(engine->adv_mode,advMode);
lua_getfield(L,-1,"dayColors");
if(lua_istable(L,-1))
{
@ -1091,6 +1175,8 @@ void lightingEngineViewscreen::defaultSettings()
levelDim=0.2f;
dayHour=-1;
daySpeed=1;
adv_mode=0;
num_diffuse=0;
dayColors.push_back(rgbf(0,0,0));
dayColors.push_back(rgbf(1,1,1));
dayColors.push_back(rgbf(0,0,0));
@ -1281,17 +1367,17 @@ rgbf lightThread::lightUpCell(rgbf power,int dx,int dy,int tx,int ty)
else
return rgbf();
}
void lightThread::doRay(const rgbf& power,int cx,int cy,int tx,int ty)
void lightThread::doRay(const rgbf& power,int cx,int cy,int tx,int ty,int num_diffuse)
{
using namespace std::placeholders;
plotLine(cx,cy,tx,ty,power,std::bind(&lightThread::lightUpCell,this,_1,_2,_3,_4,_5));
plotLineDiffuse(cx,cy,tx,ty,power,num_diffuse,std::bind(&lightThread::lightUpCell,this,_1,_2,_3,_4,_5));
}
void lightThread::doLight( int x,int y )
{
using namespace std::placeholders;
lightSource& csource=dispatch.lights[x*dispatch.getH()+y];
int num_diffuse=dispatch.num_diffusion;
if(csource.radius>0)
{
rgbf power=csource.power;
@ -1310,8 +1396,9 @@ void lightThread::doLight( int x,int y )
surrounds += lightUpCell( power, i, j,x+i, y+j); //and this is wall hack (so that walls look nice)
if(surrounds.dot(surrounds)>0.00001f) //if we needed to light up the suroundings, then raycast
{
plotSquare(x,y,radius,
std::bind(&lightThread::doRay,this,power,x,y,_1,_2));
std::bind(&lightThread::doRay,this,power,x,y,_1,_2,num_diffuse));
}
}
}
@ -1343,7 +1430,7 @@ void lightThreadDispatch::signalDoneOcclusion()
occlusionDone.notify_all();
}
lightThreadDispatch::lightThreadDispatch( lightingEngineViewscreen* p ):parent(p),lights(parent->lights),occlusion(parent->ocupancy),
lightThreadDispatch::lightThreadDispatch( lightingEngineViewscreen* p ):parent(p),lights(parent->lights),occlusion(parent->ocupancy),num_diffusion(parent->num_diffuse),
lightMap(parent->lightMap),writeCount(0),occlusionReady(false)
{

@ -47,7 +47,7 @@ private:
float light_adaptation;
rgbf adapt_to_light(const rgbf& light)
{
const float influence=0.0001;
const float influence=0.0001f;
const float max_adapt=1;
const float min_adapt=0;
float intensity=(light.r+light.g+light.b)/3.0;
@ -136,6 +136,7 @@ public:
virtual void calculate()=0;
virtual void updateWindow()=0;
virtual void preRender()=0;
virtual void loadSettings()=0;
virtual void clear()=0;
@ -225,7 +226,8 @@ public:
tthread::mutex unprocessedMutex;
std::stack<DFHack::rect2d> unprocessed; //stack of parts of map where lighting is not finished
std::vector<rgbf>& occlusion;
int& num_diffusion;
tthread::mutex writeLock; //mutex for lightMap
std::vector<rgbf>& lightMap;
@ -257,7 +259,7 @@ public:
void run();
private:
void doLight(int x,int y);
void doRay(const rgbf& power,int cx,int cy,int tx,int ty);
void doRay(const rgbf& power,int cx,int cy,int tx,int ty,int num_diffuse);
rgbf lightUpCell(rgbf power,int dx,int dy,int tx,int ty);
};
class lightingEngineViewscreen:public lightingEngine
@ -269,13 +271,13 @@ public:
void calculate();
void updateWindow();
void preRender();
void loadSettings();
void clear();
void debug(bool enable){doDebug=enable;};
private:
void fixAdvMode(int mode);
df::coord2d worldToViewportCoord(const df::coord2d& in,const DFHack::rect2d& r,const df::coord2d& window2d) ;
@ -313,6 +315,7 @@ private:
std::vector<lightSource> lights;
//Threading stuff
int num_diffuse; //under same lock as ocupancy
lightThreadDispatch threading;
//misc
void setHour(float h){dayHour=h;};
@ -346,6 +349,7 @@ private:
matLightDef matWater;
matLightDef matCitizen;
float levelDim;
int adv_mode;
//materials
std::unordered_map<std::pair<int,int>,matLightDef> matDefs;
//buildings

@ -61,6 +61,7 @@ struct dwarmode_render_hook : viewscreen_dwarfmodest{
DEFINE_VMETHOD_INTERPOSE(void,render,())
{
CoreSuspendClaimer suspend;
engine->preRender();
INTERPOSE_NEXT(render)();
engine->calculate();
engine->updateWindow();
@ -73,6 +74,7 @@ struct dungeon_render_hook : viewscreen_dungeonmodest{
DEFINE_VMETHOD_INTERPOSE(void,render,())
{
CoreSuspendClaimer suspend;
engine->preRender();
INTERPOSE_NEXT(render)();
engine->calculate();
engine->updateWindow();

@ -189,6 +189,9 @@ special.dayColors={ {0,0,0}, --dark at 0 hours
{0.5,0.5,0.5},
{0,0,0}} --dark at 24 hours
special.daySpeed=1 -- 1->1200 cur_year_ticks per day. 2->600 ticks
special.diffusionCount=1 -- split beam max 1 times to mimic diffuse lights
special.advMode=0 -- 1 or 0 different modes for adv mode. 0-> use df vision system,
-- 1(does not work)->everything visible, let rendermax light do the work
--TODO dragonfire
--materials
@ -219,4 +222,4 @@ addCreature("ELEMENTMAN_MAGMA",{0.8,0.2,0.2},{0.8,0.2,0.2},5)
--items
addItem("GEM",nil,nil,{"useMaterial","onGround"})
addItem("ROUGH",nil,nil,{"useMaterial","onGround"})
addItem("SMALLGEM",nil,nil,{"useMaterial","onGround"})
addItem("SMALLGEM",nil,nil,{"useMaterial","onGround"})