Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class W3DProjectedShadowManager : public ProjectedShadowManager
Bool init(void); ///<allocate one-time shadow assets for length of entire game.
void reset(void); ///<free all existing shadows - ready for next map.
void shutdown(void); ///<free all assets prior to shutdown of entire game.
void prepareShadows();
Int renderShadows(RenderInfoClass & rinfo); ///<iterate over each object and render its shadow onto affected objects.
void ReleaseResources(void); ///<release device dependent D3D resources.
Bool ReAcquireResources(void); ///<allocate device dependent D3D resources.
Expand All @@ -76,6 +77,8 @@ class W3DProjectedShadowManager : public ProjectedShadowManager
void flushDecals(W3DShadowTexture *texture, ShadowType type); ///<empty queue by rendering all decals with given texture

private:
Int renderProjectedTerrainShadow(W3DProjectedShadow *shadow, AABoxClass &box); ///<render shadow on map terrain.

W3DProjectedShadow *m_shadowList;
W3DProjectedShadow *m_decalList;
TextureClass *m_dynamicRenderTarget; ///<offscreen video memory texture used to render all shadow textures.
Expand All @@ -86,7 +89,12 @@ class W3DProjectedShadowManager : public ProjectedShadowManager
W3DShadowTextureManager *m_W3DShadowTextureManager;
Int m_numDecalShadows; ///< number of decal shadows in the system.
Int m_numProjectionShadows; ///< number of projected shadows in the system.
Int renderProjectedTerrainShadow(W3DProjectedShadow *shadow, AABoxClass &box); ///<render shadow on map terrain.

//Bounding rectangle around rendered portion of terrain.
Int m_drawEdgeX;
Int m_drawEdgeY;
Int m_drawStartX;
Int m_drawStartY;
};

extern W3DProjectedShadowManager *TheW3DProjectedShadowManager;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3019,7 +3019,9 @@ void W3DModelDraw::setModelState(const ModelConditionInfo* newState)
shadowInfo.m_sizeY = tmplate->getShadowSizeY();
shadowInfo.m_offsetX = tmplate->getShadowOffsetX();
shadowInfo.m_offsetY = tmplate->getShadowOffsetY();
m_shadow = TheW3DShadowManager->addShadow(m_renderObject, &shadowInfo, draw);

DEBUG_ASSERTCRASH(m_shadow == NULL, ("m_shadow is not NULL"));
m_shadow = TheW3DShadowManager->addShadow(m_renderObject, &shadowInfo, draw);
if (m_shadow)
{ m_shadow->enableShadowInvisible(m_fullyObscuredByShroud);
m_shadow->enableShadowRender(m_shadowEnabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,6 @@ extern int nShadowStartBatchIndex;
extern int SHADOW_VERTEX_SIZE;
extern int SHADOW_INDEX_SIZE;

//Bounding rectangle around rendered portion of terrain.
static Int drawEdgeX=0;
static Int drawEdgeY=0;
static Int drawStartX=0;
static Int drawStartY=0;

//Global streaming vertex buffer with x,y,z,u,v type.
struct SHADOW_DECAL_VERTEX //vertex structure passed to D3D
{
Expand Down Expand Up @@ -215,6 +209,10 @@ W3DProjectedShadowManager::W3DProjectedShadowManager(void)
m_W3DShadowTextureManager = NULL;
m_shadowCamera = NULL;
m_shadowContext= NULL;
m_drawEdgeX = 0;
m_drawEdgeY = 0;
m_drawStartX = 0;
m_drawStartY = 0;
}

W3DProjectedShadowManager::~W3DProjectedShadowManager(void)
Expand Down Expand Up @@ -959,15 +957,15 @@ void W3DProjectedShadowManager::queueDecal(W3DProjectedShadow *shadow)
Int startY=REAL_TO_INT_FLOOR(((objPos.Y+min_y)*mapScaleInv)) + borderSize;
Int endY=REAL_TO_INT_CEIL(((objPos.Y+max_y)*mapScaleInv)) + borderSize;

startX = __max(startX,drawStartX);
startX = __min(startX,drawEdgeX);
startY = __max(startY,drawStartY);
startY = __min(startY,drawEdgeY);
startX = __max(startX,m_drawStartX);
startX = __min(startX,m_drawEdgeX);
startY = __max(startY,m_drawStartY);
startY = __min(startY,m_drawEdgeY);

endX = __max(endX,drawStartX);
endX = __min(endX,drawEdgeX);
endY = __max(endY,drawStartY);
endY = __min(endY,drawEdgeY);
endX = __max(endX,m_drawStartX);
endX = __min(endX,m_drawEdgeX);
endY = __max(endY,m_drawStartY);
endY = __min(endY,m_drawEdgeY);

//Check if decal too large to fit inside 65536 index buffer.
//try clipping each direction to < 104 since that's more than
Expand Down Expand Up @@ -1276,33 +1274,40 @@ void W3DProjectedShadowManager::queueSimpleDecal(W3DProjectedShadow *shadow)

}

void W3DProjectedShadowManager::prepareShadows()
{
if (!TheTerrainRenderObject)
return;

WorldHeightMap *hmap=TheTerrainRenderObject->getMap();

if (!hmap)
return;

//Find extents of visible terrain
m_drawEdgeY=hmap->getDrawOrgY()+hmap->getDrawHeight()-1;
m_drawEdgeX=hmap->getDrawOrgX()+hmap->getDrawWidth()-1;
if (m_drawEdgeX > (hmap->getXExtent()-1))
m_drawEdgeX = hmap->getXExtent()-1;
if (m_drawEdgeY > (hmap->getYExtent()-1))
m_drawEdgeY = hmap->getYExtent()-1;
m_drawStartX=hmap->getDrawOrgX();
m_drawStartY=hmap->getDrawOrgY();
}

Int W3DProjectedShadowManager::renderShadows(RenderInfoClass & rinfo)
{
///@todo: implement this method.
W3DProjectedShadow *shadow;
static AABoxClass aaBox;
static SphereClass sphere;
Int projectionCount=0;

if (!TheTerrainRenderObject)
return projectionCount;

if (!m_shadowList && !m_decalList)
return projectionCount; //there are no shadows to render.

//Find extents of visible terrain
if (TheTerrainRenderObject)
{
WorldHeightMap *hmap=TheTerrainRenderObject->getMap();

drawEdgeY=hmap->getDrawOrgY()+hmap->getDrawHeight()-1;
drawEdgeX=hmap->getDrawOrgX()+hmap->getDrawWidth()-1;
if (drawEdgeX > (hmap->getXExtent()-1))
drawEdgeX = hmap->getXExtent()-1;
if (drawEdgeY > (hmap->getYExtent()-1))
drawEdgeY = hmap->getYExtent()-1;
drawStartX=hmap->getDrawOrgX();
drawStartY=hmap->getDrawOrgY();
}
else
return projectionCount;
W3DProjectedShadow *shadow;
static AABoxClass aaBox;
static SphereClass sphere;

//According to Nvidia there's a D3D bug that happens if you don't start with a
//new dynamic VB each frame - so we force a DISCARD by overflowing the counter.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ Vector3 LightPosWorld[ MAX_SHADOW_LIGHTS ] =
Vector3( 94.0161f, 50.499f, 200.0f)
};

void PrepareShadows()
{
if (TheW3DProjectedShadowManager)
TheW3DProjectedShadowManager->prepareShadows();
}

//DECLARE_PERF_TIMER(shadowsRender)
void DoShadows(RenderInfoClass & rinfo, Bool stencilPass)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
// DEFINITIONS ////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///@todo: Remove these globals since we no longer need W3D to call them for us.
extern void PrepareShadows();
extern void DoTrees(RenderInfoClass & rinfo);
extern void DoShadows(RenderInfoClass & rinfo, Bool stencilPass);
extern void DoParticles(RenderInfoClass & rinfo);
Expand Down Expand Up @@ -789,6 +790,10 @@ void RTS3DScene::renderOneObject(RenderInfoClass &rinfo, RenderObjClass *robj, I
/**Draw everything that was submitted from this scene*/
void RTS3DScene::Flush(RenderInfoClass & rinfo)
{
// TheSuperHackers @bugfix Now always prepares shadows to guarantee correct state before doing any
// shadow draw calls. Originally just drawing shadows for trees would not properly prepare shadows.
PrepareShadows();

//don't draw shadows in this mode because they interfere with destination alpha or are invisible (wireframe)
if (m_customPassMode == SCENE_PASS_DEFAULT && Get_Extra_Pass_Polygon_Mode() == EXTRA_PASS_DISABLE)
DoShadows(rinfo, false); //draw all non-stencil shadows (decals) since they fall under other objects.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class W3DProjectedShadowManager : public ProjectedShadowManager
Bool init(void); ///<allocate one-time shadow assets for length of entire game.
void reset(void); ///<free all existing shadows - ready for next map.
void shutdown(void); ///<free all assets prior to shutdown of entire game.
void prepareShadows();
Int renderShadows(RenderInfoClass & rinfo); ///<iterate over each object and render its shadow onto affected objects.
void ReleaseResources(void); ///<release device dependent D3D resources.
Bool ReAcquireResources(void); ///<allocate device dependent D3D resources.
Expand All @@ -76,6 +77,8 @@ class W3DProjectedShadowManager : public ProjectedShadowManager
void flushDecals(W3DShadowTexture *texture, ShadowType type); ///<empty queue by rendering all decals with given texture

private:
Int renderProjectedTerrainShadow(W3DProjectedShadow *shadow, AABoxClass &box); ///<render shadow on map terrain.

W3DProjectedShadow *m_shadowList;
W3DProjectedShadow *m_decalList;
TextureClass *m_dynamicRenderTarget; ///<offscreen video memory texture used to render all shadow textures.
Expand All @@ -86,7 +89,12 @@ class W3DProjectedShadowManager : public ProjectedShadowManager
W3DShadowTextureManager *m_W3DShadowTextureManager;
Int m_numDecalShadows; ///< number of decal shadows in the system.
Int m_numProjectionShadows; ///< number of projected shadows in the system.
Int renderProjectedTerrainShadow(W3DProjectedShadow *shadow, AABoxClass &box); ///<render shadow on map terrain.

//Bounding rectangle around rendered portion of terrain.
Int m_drawEdgeX;
Int m_drawEdgeY;
Int m_drawStartX;
Int m_drawStartY;
};

extern W3DProjectedShadowManager *TheW3DProjectedShadowManager;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3078,7 +3078,9 @@ void W3DModelDraw::setModelState(const ModelConditionInfo* newState)
shadowInfo.m_sizeY = tmplate->getShadowSizeY();
shadowInfo.m_offsetX = tmplate->getShadowOffsetX();
shadowInfo.m_offsetY = tmplate->getShadowOffsetY();
m_shadow = TheW3DShadowManager->addShadow(m_renderObject, &shadowInfo, draw);

DEBUG_ASSERTCRASH(m_shadow == NULL, ("m_shadow is not NULL"));
m_shadow = TheW3DShadowManager->addShadow(m_renderObject, &shadowInfo, draw);
if (m_shadow)
{ m_shadow->enableShadowInvisible(m_fullyObscuredByShroud);
m_shadow->enableShadowRender(m_shadowEnabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,6 @@ extern int nShadowStartBatchIndex;
extern int SHADOW_VERTEX_SIZE;
extern int SHADOW_INDEX_SIZE;

//Bounding rectangle around rendered portion of terrain.
static Int drawEdgeX=0;
static Int drawEdgeY=0;
static Int drawStartX=0;
static Int drawStartY=0;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved these into the class.


//Global streaming vertex buffer with x,y,z,u,v type.
struct SHADOW_DECAL_VERTEX //vertex structure passed to D3D
{
Expand Down Expand Up @@ -215,6 +209,10 @@ W3DProjectedShadowManager::W3DProjectedShadowManager(void)
m_W3DShadowTextureManager = NULL;
m_shadowCamera = NULL;
m_shadowContext= NULL;
m_drawEdgeX = 0;
m_drawEdgeY = 0;
m_drawStartX = 0;
m_drawStartY = 0;
}

W3DProjectedShadowManager::~W3DProjectedShadowManager(void)
Expand Down Expand Up @@ -959,15 +957,15 @@ void W3DProjectedShadowManager::queueDecal(W3DProjectedShadow *shadow)
Int startY=REAL_TO_INT_FLOOR(((objPos.Y+min_y)*mapScaleInv)) + borderSize;
Int endY=REAL_TO_INT_CEIL(((objPos.Y+max_y)*mapScaleInv)) + borderSize;

startX = __max(startX,drawStartX);
startX = __min(startX,drawEdgeX);
startY = __max(startY,drawStartY);
startY = __min(startY,drawEdgeY);
startX = __max(startX,m_drawStartX);
startX = __min(startX,m_drawEdgeX);
startY = __max(startY,m_drawStartY);
startY = __min(startY,m_drawEdgeY);

endX = __max(endX,drawStartX);
endX = __min(endX,drawEdgeX);
endY = __max(endY,drawStartY);
endY = __min(endY,drawEdgeY);
endX = __max(endX,m_drawStartX);
endX = __min(endX,m_drawEdgeX);
endY = __max(endY,m_drawStartY);
endY = __min(endY,m_drawEdgeY);

//Check if decal too large to fit inside 65536 index buffer.
//try clipping each direction to < 104 since that's more than
Expand Down Expand Up @@ -1276,33 +1274,40 @@ void W3DProjectedShadowManager::queueSimpleDecal(W3DProjectedShadow *shadow)

}

void W3DProjectedShadowManager::prepareShadows()
{
if (!TheTerrainRenderObject)
return;

WorldHeightMap *hmap=TheTerrainRenderObject->getMap();

if (!hmap)
return;

//Find extents of visible terrain
m_drawEdgeY=hmap->getDrawOrgY()+hmap->getDrawHeight()-1;
m_drawEdgeX=hmap->getDrawOrgX()+hmap->getDrawWidth()-1;
if (m_drawEdgeX > (hmap->getXExtent()-1))
m_drawEdgeX = hmap->getXExtent()-1;
if (m_drawEdgeY > (hmap->getYExtent()-1))
m_drawEdgeY = hmap->getYExtent()-1;
m_drawStartX=hmap->getDrawOrgX();
m_drawStartY=hmap->getDrawOrgY();
}

Int W3DProjectedShadowManager::renderShadows(RenderInfoClass & rinfo)
{
///@todo: implement this method.
W3DProjectedShadow *shadow;
static AABoxClass aaBox;
static SphereClass sphere;
Int projectionCount=0;

if (!TheTerrainRenderObject)
return projectionCount;

if (!m_shadowList && !m_decalList)
return projectionCount; //there are no shadows to render.

//Find extents of visible terrain
if (TheTerrainRenderObject)
{
WorldHeightMap *hmap=TheTerrainRenderObject->getMap();

drawEdgeY=hmap->getDrawOrgY()+hmap->getDrawHeight()-1;
drawEdgeX=hmap->getDrawOrgX()+hmap->getDrawWidth()-1;
if (drawEdgeX > (hmap->getXExtent()-1))
drawEdgeX = hmap->getXExtent()-1;
if (drawEdgeY > (hmap->getYExtent()-1))
drawEdgeY = hmap->getYExtent()-1;
drawStartX=hmap->getDrawOrgX();
drawStartY=hmap->getDrawOrgY();
}
else
return projectionCount;
W3DProjectedShadow *shadow;
static AABoxClass aaBox;
static SphereClass sphere;

//According to Nvidia there's a D3D bug that happens if you don't start with a
//new dynamic VB each frame - so we force a DISCARD by overflowing the counter.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ Vector3 LightPosWorld[ MAX_SHADOW_LIGHTS ] =
Vector3( 94.0161f, 50.499f, 200.0f)
};

void PrepareShadows()
{
if (TheW3DProjectedShadowManager)
TheW3DProjectedShadowManager->prepareShadows();
}

//DECLARE_PERF_TIMER(shadowsRender)
void DoShadows(RenderInfoClass & rinfo, Bool stencilPass)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
// DEFINITIONS ////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///@todo: Remove these globals since we no longer need W3D to call them for us.
extern void PrepareShadows();
extern void DoTrees(RenderInfoClass & rinfo);
extern void DoShadows(RenderInfoClass & rinfo, Bool stencilPass);
extern void DoParticles(RenderInfoClass & rinfo);
Expand Down Expand Up @@ -827,6 +828,10 @@ void RTS3DScene::renderOneObject(RenderInfoClass &rinfo, RenderObjClass *robj, I
/**Draw everything that was submitted from this scene*/
void RTS3DScene::Flush(RenderInfoClass & rinfo)
{
// TheSuperHackers @bugfix Now always prepares shadows to guarantee correct state before doing any
// shadow draw calls. Originally just drawing shadows for trees would not properly prepare shadows.
PrepareShadows();

//don't draw shadows in this mode because they interfere with destination alpha or are invisible (wireframe)
if (m_customPassMode == SCENE_PASS_DEFAULT && Get_Extra_Pass_Polygon_Mode() == EXTRA_PASS_DISABLE)
DoShadows(rinfo, false); //draw all non-stencil shadows (decals) since they fall under other objects.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1604,12 +1604,12 @@ void W3DTreeBuffer::drawTrees(CameraClass * camera, RefRenderObjListIterator *pD
if (!m_trees[curTree].visible || !m_treeTypes[type].m_doShadow) {
continue;
}
Real factor = 1.0f;

if (m_trees[curTree].m_toppleState == TOPPLE_FALLING ||
m_trees[curTree].m_toppleState == TOPPLE_DOWN) {
continue;
}
m_shadow->setSize(m_treeTypes[type].m_shadowSize, -m_treeTypes[type].m_shadowSize*factor);
m_shadow->setSize(m_treeTypes[type].m_shadowSize, m_treeTypes[type].m_shadowSize);
Copy link
Author

@xezon xezon Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change does not exactly relate to the fix, but is related to tree shadows. Essentially Y was flipped which should flip the texture, but that does not make a difference because the decal shadow is a dark circle and inconsequential to flipping.

m_shadow->setPosition(m_trees[curTree].location.X, m_trees[curTree].location.Y, m_trees[curTree].location.Z);
TheW3DProjectedShadowManager->queueDecal(m_shadow);
}
Expand Down
Loading