diff --git a/src/core/config.h b/src/core/config.h
index d813a1f2..2422ab13 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -73,6 +73,7 @@ enum Config {
 	NUMCORONAS = 56,
 	NUMPOINTLIGHTS = 32,
 	NUM3DMARKERS = 32,
+	NUMSHINYTEXTS = 32,
 	NUMMONEYMESSAGES = 16,
 	NUMPICKUPMESSAGES = 16,
 	NUMBULLETTRACES = 16,
diff --git a/src/render/Shadows.h b/src/render/Shadows.h
index 982cc463..fb41ebbc 100644
--- a/src/render/Shadows.h
+++ b/src/render/Shadows.h
@@ -175,11 +175,18 @@ public:
 	static void RenderIndicatorShadow        (uint32 nID, uint8 ShadowType, RwTexture *pTexture,  CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity);
 };
 
-extern RwTexture *&gpBloodPoolTex;
+extern RwTexture *&gpShadowCarTex;
+extern RwTexture *&gpShadowPedTex;
+extern RwTexture *&gpShadowHeliTex;
 extern RwTexture *&gpShadowExplosionTex;
 extern RwTexture *&gpShadowHeadLightsTex;
-extern RwTexture *&gpGoalTex;
 extern RwTexture *&gpOutline1Tex;
 extern RwTexture *&gpOutline2Tex;
 extern RwTexture *&gpOutline3Tex;
+extern RwTexture *&gpBloodPoolTex;
+extern RwTexture *&gpReflectionTex;
+extern RwTexture *&gpGoalMarkerTex;
+extern RwTexture *&gpWalkDontTex;
 extern RwTexture *&gpCrackedGlassTex;
+extern RwTexture *&gpPostShadowTex;
+extern RwTexture *&gpGoalTex;
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index 301ae265..71fca3ba 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -1,6 +1,7 @@
 #include "common.h"
 #include "patcher.h"
 #include "SpecialFX.h"
+#include "RenderBuffer.h"
 #include "Timer.h"
 #include "Sprite.h"
 #include "Font.h"
@@ -12,6 +13,7 @@
 #include "VisibilityPlugins.h"
 #include "World.h"
 #include "Particle.h"
+#include "Shadows.h"
 #include "General.h"
 #include "Camera.h"
 #include "Shadows.h"
@@ -26,7 +28,7 @@ WRAPPER void CMotionBlurStreaks::RegisterStreak(int32 id, uint8 r, uint8 g, uint
 
 
 CBulletTrace (&CBulletTraces::aTraces)[NUMBULLETTRACES] = *(CBulletTrace(*)[NUMBULLETTRACES])*(uintptr*)0x72B1B8;
-RxObjSpace3DVertex (&TraceVertices)[6] = *(RxObjSpace3DVertex(*)[6])*(uintptr*)0x649884;
+RxObjSpace3DVertex (&TraceVertices)[6] = *(RxObjSpace3DVertex(*)[6])*(uintptr*)0x649884;
 RwImVertexIndex (&TraceIndexList)[12] = *(RwImVertexIndex(*)[12])*(uintptr*)0x64986C;
 
 void CBulletTraces::Init(void)
@@ -81,8 +83,8 @@ void CBulletTraces::Render(void)
 			RwIm3DEnd();
 		}
 	}
-	RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
-	RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5);
+	RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
+	RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5);
 	RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6);
 }
 
@@ -402,6 +404,151 @@ C3dMarkers::Update()
 {
 }
 
+
+int CShinyTexts::NumShinyTexts;
+CShinyText CShinyTexts::aShinyTexts[NUMSHINYTEXTS];
+
+void
+CShinyTexts::Init(void)
+{
+	NumShinyTexts = 0;
+}
+
+void
+CShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
+	float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,
+	uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist)
+{
+	if(NumShinyTexts >= NUMSHINYTEXTS)
+		return;
+
+	aShinyTexts[NumShinyTexts].m_camDist = (p0 - TheCamera.GetPosition()).Magnitude();
+	if(aShinyTexts[NumShinyTexts].m_camDist > maxDist)
+		return;
+	aShinyTexts[NumShinyTexts].m_verts[0] = p0;
+	aShinyTexts[NumShinyTexts].m_verts[1] = p1;
+	aShinyTexts[NumShinyTexts].m_verts[2] = p2;
+	aShinyTexts[NumShinyTexts].m_verts[3] = p3;
+	aShinyTexts[NumShinyTexts].m_texCoords[0].x = u0;
+	aShinyTexts[NumShinyTexts].m_texCoords[0].y = v0;
+	aShinyTexts[NumShinyTexts].m_texCoords[1].x = u1;
+	aShinyTexts[NumShinyTexts].m_texCoords[1].y = v1;
+	aShinyTexts[NumShinyTexts].m_texCoords[2].x = u2;
+	aShinyTexts[NumShinyTexts].m_texCoords[2].y = v2;
+	aShinyTexts[NumShinyTexts].m_texCoords[3].x = u3;
+	aShinyTexts[NumShinyTexts].m_texCoords[3].y = v3;
+	aShinyTexts[NumShinyTexts].m_type = type;
+	aShinyTexts[NumShinyTexts].m_red = red;
+	aShinyTexts[NumShinyTexts].m_green = green;
+	aShinyTexts[NumShinyTexts].m_blue = blue;
+	// Fade out at half the max dist
+	float halfDist = maxDist*0.5f;
+	if(aShinyTexts[NumShinyTexts].m_camDist > halfDist){
+		float f = 1.0f - (aShinyTexts[NumShinyTexts].m_camDist - halfDist)/halfDist;
+		aShinyTexts[NumShinyTexts].m_red *= f;
+		aShinyTexts[NumShinyTexts].m_green *= f;
+		aShinyTexts[NumShinyTexts].m_blue *= f;
+	}
+
+	NumShinyTexts++;
+}
+
+void
+CShinyTexts::Render(void)
+{
+	int i, ix, v;
+	RwTexture *lastTex = nil;
+
+	if(NumShinyTexts == 0)
+		return;
+
+	RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+	RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+	RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+	RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+
+	TempBufferVerticesStored = 0;
+	TempBufferIndicesStored = 0;
+
+	for(i = 0; i < NumShinyTexts; i++){
+		if(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-64 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-62)
+			RenderOutGeometryBuffer();
+
+		uint8 r = aShinyTexts[i].m_red;
+		uint8 g = aShinyTexts[i].m_green;
+		uint8 b = aShinyTexts[i].m_blue;
+
+		switch(aShinyTexts[i].m_type){
+		case SHINYTEXT_WALK:
+			if(lastTex != gpWalkDontTex){
+				RenderOutGeometryBuffer();
+				RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpWalkDontTex));
+				lastTex = gpWalkDontTex;
+			}
+	quad:
+			v = TempBufferVerticesStored;
+			RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+0], r, g, b, 255);
+			RwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_verts[0].x, aShinyTexts[i].m_verts[0].y, aShinyTexts[i].m_verts[0].z);
+			RwIm3DVertexSetU(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_texCoords[0].x);
+			RwIm3DVertexSetV(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_texCoords[0].y);
+			RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], r, g, b, 255);
+			RwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_verts[1].x, aShinyTexts[i].m_verts[1].y, aShinyTexts[i].m_verts[1].z);
+			RwIm3DVertexSetU(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_texCoords[1].x);
+			RwIm3DVertexSetV(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_texCoords[1].y);
+			RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], r, g, b, 255);
+			RwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_verts[2].x, aShinyTexts[i].m_verts[2].y, aShinyTexts[i].m_verts[2].z);
+			RwIm3DVertexSetU(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_texCoords[2].x);
+			RwIm3DVertexSetV(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_texCoords[2].y);
+			RwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], r, g, b, 255);
+			RwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_verts[3].x, aShinyTexts[i].m_verts[3].y, aShinyTexts[i].m_verts[3].z);
+			RwIm3DVertexSetU(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_texCoords[3].x);
+			RwIm3DVertexSetV(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_texCoords[3].y);
+			ix = TempBufferIndicesStored;
+			TempBufferRenderIndexList[ix+0] = 0 + TempBufferVerticesStored;
+			TempBufferRenderIndexList[ix+1] = 1 + TempBufferVerticesStored;
+			TempBufferRenderIndexList[ix+2] = 2 + TempBufferVerticesStored;
+			TempBufferRenderIndexList[ix+3] = 2 + TempBufferVerticesStored;
+			TempBufferRenderIndexList[ix+4] = 1 + TempBufferVerticesStored;
+			TempBufferRenderIndexList[ix+5] = 3 + TempBufferVerticesStored;
+			TempBufferVerticesStored += 4;
+			TempBufferIndicesStored += 6;
+			break;
+
+		case SHINYTEXT_FLAT:
+			if(lastTex != nil){
+				RenderOutGeometryBuffer();
+				RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+				lastTex = nil;
+			}
+			goto quad;
+		}
+	}
+
+	RenderOutGeometryBuffer();
+	NumShinyTexts = 0;
+
+	RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+	RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+	RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+	RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+}
+
+void
+CShinyTexts::RenderOutGeometryBuffer(void)
+{
+	if(TempBufferIndicesStored != 0){
+		LittleTest();
+		if(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){
+			RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);
+			RwIm3DEnd();
+		}
+		TempBufferVerticesStored = 0;
+		TempBufferIndicesStored = 0;
+	}
+}
+
+
+
 #define MONEY_MESSAGE_LIFETIME_MS 2000
 
 CMoneyMessage CMoneyMessages::aMoneyMessages[NUMMONEYMESSAGES];
@@ -564,6 +711,11 @@ STARTPATCHES
 	InjectHook(0x51B400, C3dMarkers::Render, PATCH_JUMP);
 	InjectHook(0x51B3B0, C3dMarkers::Shutdown, PATCH_JUMP);
 	
+	InjectHook(0x51A5A0, CShinyTexts::Init, PATCH_JUMP);
+	InjectHook(0x51AAB0, CShinyTexts::RegisterOne, PATCH_JUMP);
+	InjectHook(0x51A5B0, CShinyTexts::Render, PATCH_JUMP);
+	InjectHook(0x51AA50, CShinyTexts::RenderOutGeometryBuffer, PATCH_JUMP);
+
 	InjectHook(0x51AF70, CMoneyMessages::Init, PATCH_JUMP);
 	InjectHook(0x51B030, CMoneyMessages::Render, PATCH_JUMP);
 ENDPATCHES
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index fc155a53..22ee502e 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -57,27 +57,27 @@ enum
 
 
 class C3dMarker
-{
-public:
-	CMatrix m_Matrix;
-	RpAtomic *m_pAtomic;
-	RpMaterial *m_pMaterial;
-	uint16 m_nType;
-	bool m_bIsUsed;
-	uint32 m_nIdentifier;
-	RwRGBA m_Color;
-	uint16 m_nPulsePeriod;
-	int16 m_nRotateRate;
-	uint32 m_nStartTime;
-	float m_fPulseFraction;
-	float m_fStdSize;
-	float m_fSize;
-	float m_fBrightness;
-	float m_fCameraRange;
-
-	bool AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
-	void DeleteMarkerObject();
-	void Render();
+{
+public:
+	CMatrix m_Matrix;
+	RpAtomic *m_pAtomic;
+	RpMaterial *m_pMaterial;
+	uint16 m_nType;
+	bool m_bIsUsed;
+	uint32 m_nIdentifier;
+	RwRGBA m_Color;
+	uint16 m_nPulsePeriod;
+	int16 m_nRotateRate;
+	uint32 m_nStartTime;
+	float m_fPulseFraction;
+	float m_fStdSize;
+	float m_fSize;
+	float m_fBrightness;
+	float m_fCameraRange;
+
+	bool AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
+	void DeleteMarkerObject();
+	void Render();
 };
 
 class C3dMarkers
@@ -87,42 +87,73 @@ public:
 	static void Shutdown();
 	static C3dMarker *PlaceMarker(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
 	static void PlaceMarkerSet(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
-	static void Render();
+	static void Render();
 	static void Update();
 
 	static C3dMarker(&m_aMarkerArray)[NUM3DMARKERS];
 	static int32 &NumActiveMarkers;
 	static RpClump* (&m_pRpClumpArray)[NUMMARKERTYPES];
-};
-
-class CMoneyMessage
-{
-	friend class CMoneyMessages;
-
-	uint32	m_nTimeRegistered;
-	CVector	m_vecPosition;
-	wchar	m_aText[16];
-	CRGBA	m_Colour;
-	float	m_fSize;
-	float	m_fOpacity;
-public:
-	void Render();
-};
-
-class CMoneyMessages
-{
-	static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES];
-public:
-	static void Init();
-	static void Render();
-	static void	RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity);
-};
-
-class CSpecialParticleStuff
-{
-	static uint32 BoatFromStart;
-public:
-	static void CreateFoamAroundObject(CMatrix*, float, float, float, int32);
-	static void StartBoatFoamAnimation();
-	static void UpdateBoatFoamAnimation(CMatrix*);
-};
+};
+
+enum
+{
+	SHINYTEXT_WALK = 1,
+	SHINYTEXT_FLAT
+};
+
+class CShinyText
+{
+public:
+	CVector m_verts[4];
+	CVector2D m_texCoords[4];
+	float m_camDist;
+	uint8 m_type;
+	uint8 m_red;
+	uint8 m_green;
+	uint8 m_blue;
+};
+
+class CShinyTexts
+{
+	static int NumShinyTexts;
+	static CShinyText aShinyTexts[NUMSHINYTEXTS];
+public:
+	static void Init(void);
+	static void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,
+		float u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,
+		uint8 type, uint8 red, uint8 green, uint8 blue, float maxDist);
+	static void Render(void);
+	static void RenderOutGeometryBuffer(void);
+};
+
+class CMoneyMessage
+{
+	friend class CMoneyMessages;
+
+	uint32	m_nTimeRegistered;
+	CVector	m_vecPosition;
+	wchar	m_aText[16];
+	CRGBA	m_Colour;
+	float	m_fSize;
+	float	m_fOpacity;
+public:
+	void Render();
+};
+
+class CMoneyMessages
+{
+	static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES];
+public:
+	static void Init();
+	static void Render();
+	static void	RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity);
+};
+
+class CSpecialParticleStuff
+{
+	static uint32 BoatFromStart;
+public:
+	static void CreateFoamAroundObject(CMatrix*, float, float, float, int32);
+	static void StartBoatFoamAnimation();
+	static void UpdateBoatFoamAnimation(CMatrix*);
+};