summaryrefslogtreecommitdiffstats
path: root/src/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/render')
-rw-r--r--src/render/Renderer.cpp609
-rw-r--r--src/render/Renderer.h18
-rw-r--r--src/render/SpecialFX.cpp35
-rw-r--r--src/render/WaterLevel.cpp4
-rw-r--r--src/render/Weather.cpp20
5 files changed, 662 insertions, 24 deletions
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 2559b743..53971f95 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -1,3 +1,4 @@
+#define WITH_D3D
#include "common.h"
#include "main.h"
@@ -6,6 +7,7 @@
#include "Treadable.h"
#include "Ped.h"
#include "Vehicle.h"
+#include "Boat.h"
#include "Heli.h"
#include "Object.h"
#include "PathFind.h"
@@ -68,6 +70,12 @@ int32 CRenderer::ms_nNoOfVisibleEntities;
CEntity *CRenderer::ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES];
CEntity *CRenderer::ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES];
int32 CRenderer::ms_nNoOfInVisibleEntities;
+#ifdef NEW_RENDERER
+int32 CRenderer::ms_nNoOfVisibleVehicles;
+CEntity *CRenderer::ms_aVisibleVehiclePtrs[NUMVISIBLEENTITIES];
+int32 CRenderer::ms_nNoOfVisibleBuildings;
+CEntity *CRenderer::ms_aVisibleBuildingPtrs[NUMVISIBLEENTITIES];
+#endif
CVector CRenderer::ms_vecCameraPosition;
CVehicle *CRenderer::m_pFirstPersonVehicle;
@@ -109,6 +117,20 @@ CRenderer::PreRender(void)
for(i = 0; i < ms_nNoOfVisibleEntities; i++)
ms_aVisibleEntityPtrs[i]->PreRender();
+#ifdef NEW_RENDERER
+ if(gbNewRenderer){
+ for(i = 0; i < ms_nNoOfVisibleVehicles; i++)
+ ms_aVisibleVehiclePtrs[i]->PreRender();
+ // How is this done with cWorldStream?
+ for(i = 0; i < ms_nNoOfVisibleBuildings; i++)
+ ms_aVisibleBuildingPtrs[i]->PreRender();
+ for(node = CVisibilityPlugins::m_alphaBuildingList.head.next;
+ node != &CVisibilityPlugins::m_alphaBuildingList.tail;
+ node = node->next)
+ ((CEntity*)node->item.entity)->PreRender();
+ }
+#endif
+
for (i = 0; i < ms_nNoOfInVisibleEntities; i++) {
#ifdef SQUEEZE_PERFORMANCE
if (ms_aInVisibleEntityPtrs[i]->IsVehicle() && ((CVehicle*)ms_aInVisibleEntityPtrs[i])->IsHeli())
@@ -241,6 +263,8 @@ CRenderer::RenderFirstPersonVehicle(void)
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
}
+inline bool IsRoad(CEntity *e) { return e->IsBuilding() && ((CBuilding*)e)->GetIsATreadable(); }
+
void
CRenderer::RenderRoads(void)
{
@@ -254,7 +278,7 @@ CRenderer::RenderRoads(void)
for(i = 0; i < ms_nNoOfVisibleEntities; i++){
t = (CTreadable*)ms_aVisibleEntityPtrs[i];
- if(t->IsBuilding() && t->GetIsATreadable()){
+ if(IsRoad(t)){
#ifndef MASTER
if(gbShowCarRoadGroups || gbShowPedRoadGroups){
int ind = 0;
@@ -288,7 +312,7 @@ CRenderer::RenderEverythingBarRoads(void)
for(i = 0; i < ms_nNoOfVisibleEntities; i++){
e = ms_aVisibleEntityPtrs[i];
- if(e->IsBuilding() && ((CBuilding*)e)->GetIsATreadable())
+ if(IsRoad(e))
continue;
#ifdef EXTENDED_PIPELINES
@@ -349,6 +373,556 @@ CRenderer::RenderBoats(void)
}
}
+#ifdef NEW_RENDERER
+#ifndef LIBRW
+#error "Need librw for EXTENDED_PIPELINES"
+#endif
+#include "WaterLevel.h"
+
+enum {
+ // blend passes
+ PASS_NOZ, // no z-write
+ PASS_ADD, // additive
+ PASS_BLEND // normal blend
+};
+
+static RwRGBAReal black;
+
+static void
+SetStencilState(int state)
+{
+ switch(state){
+ // disable stencil
+ case 0:
+ rw::SetRenderState(rw::STENCILENABLE, FALSE);
+ break;
+ // test against stencil
+ case 1:
+ rw::SetRenderState(rw::STENCILENABLE, TRUE);
+ rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILNOTEQUAL);
+ rw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP);
+ rw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP);
+ rw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP);
+ rw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFF);
+ rw::SetRenderState(rw::STENCILFUNCTIONREF, 0xFF);
+ break;
+ // write to stencil
+ case 2:
+ rw::SetRenderState(rw::STENCILENABLE, TRUE);
+ rw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS);
+ rw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE);
+ rw::SetRenderState(rw::STENCILFUNCTIONREF, 0xFF);
+ break;
+ }
+}
+
+#ifdef RW_D3D9
+struct BuildingInst
+{
+ rw::RawMatrix combinedMat;
+ rw::d3d9::InstanceDataHeader *instHeader;
+ uint8 fadeAlpha;
+ bool lighting;
+};
+static BuildingInst blendInsts[3][2000];
+static int numBlendInsts[3];
+
+static void
+SetMatrix(BuildingInst *building, rw::Matrix *worldMat)
+{
+ using namespace rw;
+ RawMatrix world, worldview;
+ Camera *cam = engine->currentCamera;
+ convMatrix(&world, worldMat);
+ RawMatrix::mult(&worldview, &world, &cam->devView);
+ RawMatrix::mult(&building->combinedMat, &worldview, &cam->devProj);
+}
+
+static bool
+IsTextureTransparent(RwTexture *tex)
+{
+ if(tex == nil || tex->raster == nil)
+ return false;
+ return PLUGINOFFSET(rw::d3d::D3dRaster, tex->raster, rw::d3d::nativeRasterOffset)->hasAlpha;
+}
+
+// Render all opaque meshes and put atomics that needs blending
+// into the deferred list.
+static void
+AtomicFirstPass(RpAtomic *atomic, int pass)
+{
+ using namespace rw;
+ using namespace rw::d3d;
+ using namespace rw::d3d9;
+
+ BuildingInst *building = &blendInsts[pass][numBlendInsts[pass]];
+
+ atomic->getPipeline()->instance(atomic);
+ building->instHeader = (d3d9::InstanceDataHeader*)atomic->geometry->instData;
+ assert(building->instHeader != nil);
+ assert(building->instHeader->platform == PLATFORM_D3D9);
+ building->fadeAlpha = 255;
+ building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);
+
+ bool setupDone = false;
+ bool defer = false;
+ SetMatrix(building, atomic->getFrame()->getLTM());
+
+ InstanceData *inst = building->instHeader->inst;
+ for(rw::uint32 i = 0; i < building->instHeader->numMeshes; i++, inst++){
+ Material *m = inst->material;
+
+ if(inst->vertexAlpha || m->color.alpha != 255 ||
+ IsTextureTransparent(m->texture)){
+ defer = true;
+ continue;
+ }
+
+ // alright we're rendering this atomic
+ if(!setupDone){
+ setStreamSource(0, building->instHeader->vertexStream[0].vertexBuffer, 0, building->instHeader->vertexStream[0].stride);
+ setIndices(building->instHeader->indexBuffer);
+ setVertexDeclaration(building->instHeader->vertexDeclaration);
+ setVertexShader(default_amb_VS);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&building->combinedMat, 4);
+ if(building->lighting)
+ setAmbient(pAmbient->color);
+ else
+ setAmbient(black);
+ setupDone = true;
+ }
+
+ setMaterial(m->color, m->surfaceProps);
+
+ if(m->texture){
+ d3d::setTexture(0, m->texture);
+ setPixelShader(default_tex_PS);
+ }else
+ setPixelShader(default_PS);
+
+ drawInst(building->instHeader, inst);
+ }
+ if(defer)
+ numBlendInsts[pass]++;
+}
+
+static void
+AtomicFullyTransparent(RpAtomic *atomic, int pass, int fadeAlpha)
+{
+ using namespace rw;
+ using namespace rw::d3d;
+ using namespace rw::d3d9;
+
+ BuildingInst *building = &blendInsts[pass][numBlendInsts[pass]];
+
+ atomic->getPipeline()->instance(atomic);
+ building->instHeader = (d3d9::InstanceDataHeader*)atomic->geometry->instData;
+ assert(building->instHeader != nil);
+ assert(building->instHeader->platform == PLATFORM_D3D9);
+ building->fadeAlpha = fadeAlpha;
+ building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);
+ SetMatrix(building, atomic->getFrame()->getLTM());
+ numBlendInsts[pass]++;
+}
+
+static void
+RenderBlendPass(int pass)
+{
+ using namespace rw;
+ using namespace rw::d3d;
+ using namespace rw::d3d9;
+
+ setVertexShader(default_amb_VS);
+
+ int i;
+ for(i = 0; i < numBlendInsts[pass]; i++){
+ BuildingInst *building = &blendInsts[pass][i];
+
+ setStreamSource(0, building->instHeader->vertexStream[0].vertexBuffer, 0, building->instHeader->vertexStream[0].stride);
+ setIndices(building->instHeader->indexBuffer);
+ setVertexDeclaration(building->instHeader->vertexDeclaration);
+ d3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&building->combinedMat, 4);
+ if(building->lighting)
+ setAmbient(pAmbient->color);
+ else
+ setAmbient(black);
+
+ InstanceData *inst = building->instHeader->inst;
+ for(rw::uint32 j = 0; j < building->instHeader->numMeshes; j++, inst++){
+ Material *m = inst->material;
+ if(!inst->vertexAlpha && m->color.alpha == 255 && !IsTextureTransparent(m->texture) && building->fadeAlpha == 255)
+ continue; // already done this one
+
+ rw::RGBA color = m->color;
+ color.alpha = (color.alpha * building->fadeAlpha)/255;
+ setMaterial(color, m->surfaceProps);
+
+ if(m->texture){
+ d3d::setTexture(0, m->texture);
+ setPixelShader(default_tex_PS);
+ }else
+ setPixelShader(default_PS);
+
+ drawInst(building->instHeader, inst);
+ }
+ }
+}
+#endif
+#ifdef RW_GL3
+struct BuildingInst
+{
+ rw::Matrix matrix;
+ rw::gl3::InstanceDataHeader *instHeader;
+ uint8 fadeAlpha;
+ bool lighting;
+};
+static BuildingInst blendInsts[3][2000];
+static int numBlendInsts[3];
+
+static bool
+IsTextureTransparent(RwTexture *tex)
+{
+ if(tex == nil || tex->raster == nil)
+ return false;
+ return PLUGINOFFSET(rw::gl3::Gl3Raster, tex->raster, rw::gl3::nativeRasterOffset)->hasAlpha;
+}
+
+// Render all opaque meshes and put atomics that needs blending
+// into the deferred list.
+static void
+AtomicFirstPass(RpAtomic *atomic, int pass)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ BuildingInst *building = &blendInsts[pass][numBlendInsts[pass]];
+
+ atomic->getPipeline()->instance(atomic);
+ building->instHeader = (gl3::InstanceDataHeader*)atomic->geometry->instData;
+ assert(building->instHeader != nil);
+ assert(building->instHeader->platform == PLATFORM_GL3);
+ building->fadeAlpha = 255;
+ building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);
+
+ WorldLights lights;
+ lights.numAmbients = 1;
+ lights.numDirectionals = 0;
+ lights.numLocals = 0;
+ if(building->lighting)
+ lights.ambient = pAmbient->color;
+ else
+ lights.ambient = black;
+
+ bool setupDone = false;
+ bool defer = false;
+ building->matrix = *atomic->getFrame()->getLTM();
+
+ InstanceData *inst = building->instHeader->inst;
+ for(rw::uint32 i = 0; i < building->instHeader->numMeshes; i++, inst++){
+ Material *m = inst->material;
+
+ if(inst->vertexAlpha || m->color.alpha != 255 ||
+ IsTextureTransparent(m->texture)){
+ defer = true;
+ continue;
+ }
+
+ // alright we're rendering this atomic
+ if(!setupDone){
+ defaultShader->use();
+ setWorldMatrix(&building->matrix);
+#ifdef RW_GL_USE_VAOS
+ glBindVertexArray(building->instHeader->vao);
+#else
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, building->instHeader->ibo);
+ glBindBuffer(GL_ARRAY_BUFFER, building->instHeader->vbo);
+ setAttribPointers(building->instHeader->attribDesc, building->instHeader->numAttribs);
+#endif
+ setLights(&lights);
+ setupDone = true;
+ }
+
+ setMaterial(m->color, m->surfaceProps);
+
+ setTexture(0, m->texture);
+
+ drawInst(building->instHeader, inst);
+ }
+#ifndef RW_GL_USE_VAOS
+ disableAttribPointers(building->instHeader->attribDesc, building->instHeader->numAttribs);
+#endif
+ if(defer)
+ numBlendInsts[pass]++;
+}
+
+static void
+AtomicFullyTransparent(RpAtomic *atomic, int pass, int fadeAlpha)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ BuildingInst *building = &blendInsts[pass][numBlendInsts[pass]];
+
+ atomic->getPipeline()->instance(atomic);
+ building->instHeader = (gl3::InstanceDataHeader*)atomic->geometry->instData;
+ assert(building->instHeader != nil);
+ assert(building->instHeader->platform == PLATFORM_GL3);
+ building->fadeAlpha = fadeAlpha;
+ building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);
+ building->matrix = *atomic->getFrame()->getLTM();
+ numBlendInsts[pass]++;
+}
+
+static void
+RenderBlendPass(int pass)
+{
+ using namespace rw;
+ using namespace rw::gl3;
+
+ defaultShader->use();
+ WorldLights lights;
+ lights.numAmbients = 1;
+ lights.numDirectionals = 0;
+ lights.numLocals = 0;
+
+ int i;
+ for(i = 0; i < numBlendInsts[pass]; i++){
+ BuildingInst *building = &blendInsts[pass][i];
+
+#ifdef RW_GL_USE_VAOS
+ glBindVertexArray(building->instHeader->vao);
+#else
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, building->instHeader->ibo);
+ glBindBuffer(GL_ARRAY_BUFFER, building->instHeader->vbo);
+ setAttribPointers(building->instHeader->attribDesc, building->instHeader->numAttribs);
+#endif
+ setWorldMatrix(&building->matrix);
+ if(building->lighting)
+ lights.ambient = pAmbient->color;
+ else
+ lights.ambient = black;
+ setLights(&lights);
+
+ InstanceData *inst = building->instHeader->inst;
+ for(rw::uint32 j = 0; j < building->instHeader->numMeshes; j++, inst++){
+ Material *m = inst->material;
+ if(!inst->vertexAlpha && m->color.alpha == 255 && !IsTextureTransparent(m->texture) && building->fadeAlpha == 255)
+ continue; // already done this one
+
+ rw::RGBA color = m->color;
+ color.alpha = (color.alpha * building->fadeAlpha)/255;
+ setMaterial(color, m->surfaceProps);
+
+ setTexture(0, m->texture);
+
+ drawInst(building->instHeader, inst);
+ }
+#ifndef RW_GL_USE_VAOS
+ disableAttribPointers(building->instHeader->attribDesc, building->instHeader->numAttribs);
+#endif
+ }
+}
+#endif
+
+void
+CRenderer::RenderOneBuilding(CEntity *ent, float camdist)
+{
+ if(ent->m_rwObject == nil)
+ return;
+
+ ent->bImBeingRendered = true; // TODO: this seems wrong, but do we even need it?
+
+ assert(RwObjectGetType(ent->m_rwObject) == rpATOMIC);
+ RpAtomic *atomic = (RpAtomic*)ent->m_rwObject;
+ CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->GetModelIndex());
+
+ int pass = PASS_BLEND;
+ if(mi->m_additive) // very questionable
+ pass = PASS_ADD;
+ if(mi->m_noZwrite)
+ pass = PASS_NOZ;
+
+ if(ent->bDistanceFade){
+ RpAtomic *lodatm;
+ float fadefactor;
+ uint32 alpha;
+
+ lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE);
+ fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;
+ if(fadefactor > 1.0f)
+ fadefactor = 1.0f;
+ alpha = mi->m_alpha * fadefactor;
+
+ if(alpha == 255)
+ AtomicFirstPass(atomic, pass);
+ else{
+ // not quite sure what this is about, do we have to do that?
+ RpGeometry *geo = RpAtomicGetGeometry(lodatm);
+ if(geo != RpAtomicGetGeometry(atomic))
+ RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE);
+ AtomicFullyTransparent(atomic, pass, alpha);
+ }
+ }else
+ AtomicFirstPass(atomic, pass);
+
+ ent->bImBeingRendered = false; // TODO: this seems wrong, but do we even need it?
+}
+
+void
+CRenderer::RenderWorld(int pass)
+{
+ int i;
+ CEntity *e;
+ CLink<CVisibilityPlugins::AlphaObjectInfo> *node;
+
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ DeActivateDirectional();
+ SetAmbientColours();
+
+ // Temporary...have to figure out sorting better
+ switch(pass){
+ case 0:
+ // Roads
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ for(i = 0; i < ms_nNoOfVisibleBuildings; i++){
+ e = ms_aVisibleBuildingPtrs[i];
+ if(e->bIsBIGBuilding || IsRoad(e))
+ RenderOneBuilding(e);
+ }
+ for(node = CVisibilityPlugins::m_alphaBuildingList.tail.prev;
+ node != &CVisibilityPlugins::m_alphaBuildingList.head;
+ node = node->prev){
+ e = node->item.entity;
+ if(e->bIsBIGBuilding || IsRoad(e))
+ RenderOneBuilding(e, node->item.sort);
+ }
+
+ // KLUDGE for road puddles which have to be rendered at road-time
+ // only very temporary, there are more rendering issues
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RenderBlendPass(PASS_BLEND);
+ numBlendInsts[PASS_BLEND] = 0;
+ break;
+ case 1:
+ // Opaque
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ for(i = 0; i < ms_nNoOfVisibleBuildings; i++){
+ e = ms_aVisibleBuildingPtrs[i];
+ if(!(e->bIsBIGBuilding || IsRoad(e)))
+ RenderOneBuilding(e);
+ }
+ for(node = CVisibilityPlugins::m_alphaBuildingList.tail.prev;
+ node != &CVisibilityPlugins::m_alphaBuildingList.head;
+ node = node->prev){
+ e = node->item.entity;
+ if(!(e->bIsBIGBuilding || IsRoad(e)))
+ RenderOneBuilding(e, node->item.sort);
+ }
+ // Now we have iterated through all visible buildings (unsorted and sorted)
+ // and the transparency list is done.
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
+ RenderBlendPass(PASS_NOZ);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ break;
+ case 2:
+ // Transparent
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RenderBlendPass(PASS_ADD);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RenderBlendPass(PASS_BLEND);
+ break;
+ }
+}
+
+void
+CRenderer::RenderPeds(void)
+{
+ int i;
+ CEntity *e;
+
+ for(i = 0; i < ms_nNoOfVisibleVehicles; i++){
+ e = ms_aVisibleVehiclePtrs[i];
+ if(e->IsPed())
+ RenderOneNonRoad(e);
+ }
+}
+
+void
+CRenderer::RenderVehicles(void)
+{
+ int i;
+ CEntity *e;
+ EntityInfo ei;
+ CLink<EntityInfo> *node;
+
+ // not the real thing
+ for(i = 0; i < ms_nNoOfVisibleVehicles; i++){
+ e = ms_aVisibleVehiclePtrs[i];
+ if(!e->IsVehicle())
+ continue;
+// if(PutIntoSortedVehicleList((CVehicle*)e))
+// continue; // boats handled elsewhere
+ ei.ent = e;
+ ei.sort = (ms_vecCameraPosition - e->GetPosition()).MagnitudeSqr();
+ gSortedVehiclesAndPeds.InsertSorted(ei);
+ }
+
+ for(node = gSortedVehiclesAndPeds.tail.prev;
+ node != &gSortedVehiclesAndPeds.head;
+ node = node->prev)
+ RenderOneNonRoad(node->item.ent);
+}
+
+void
+CRenderer::RenderWater(void)
+{
+ int i;
+ CEntity *e;
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+ SetStencilState(2);
+
+ for(i = 0; i < ms_nNoOfVisibleVehicles; i++){
+ e = ms_aVisibleVehiclePtrs[i];
+ if(e->IsVehicle() && ((CVehicle*)e)->IsBoat())
+ ((CBoat*)e)->RenderWaterOutPolys();
+ }
+
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ SetStencilState(1);
+
+ CWaterLevel::RenderWater();
+
+ SetStencilState(0);
+}
+
+void
+CRenderer::ClearForFrame(void)
+{
+ ms_nNoOfVisibleEntities = 0;
+ ms_nNoOfVisibleVehicles = 0;
+ ms_nNoOfVisibleBuildings = 0;
+ ms_nNoOfInVisibleEntities = 0;
+ gSortedVehiclesAndPeds.Clear();
+
+ numBlendInsts[PASS_NOZ] = 0;
+ numBlendInsts[PASS_ADD] = 0;
+ numBlendInsts[PASS_BLEND] = 0;
+}
+#endif
+
void
CRenderer::RenderFadingInEntities(void)
{
@@ -635,8 +1209,13 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent)
void
CRenderer::ConstructRenderList(void)
{
+#ifdef NEW_RENDERER
+ if(!gbNewRenderer)
+#endif
+{
ms_nNoOfVisibleEntities = 0;
ms_nNoOfInVisibleEntities = 0;
+}
ms_vecCameraPosition = TheCamera.GetPosition();
// unused
@@ -1123,6 +1702,20 @@ CRenderer::ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrL
}
void
+CRenderer::InsertEntityIntoList(CEntity *ent)
+{
+#ifdef NEW_RENDERER
+ // TODO: there are more flags being checked here
+ if(gbNewRenderer && (ent->IsVehicle() || ent->IsPed()))
+ ms_aVisibleVehiclePtrs[ms_nNoOfVisibleVehicles++] = ent;
+ else if(gbNewRenderer && ent->IsBuilding())
+ ms_aVisibleBuildingPtrs[ms_nNoOfVisibleBuildings++] = ent;
+ else
+#endif
+ ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+}
+
+void
CRenderer::ScanBigBuildingList(CPtrList &list)
{
CPtrNode *node;
@@ -1136,7 +1729,7 @@ CRenderer::ScanBigBuildingList(CPtrList &list)
#endif
if(!ent->bZoneCulled){
if(SetupBigBuildingVisibility(ent) == VIS_VISIBLE)
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ InsertEntityIntoList(ent);
#ifndef MASTER
EntitiesRendered++;
RenderedBigBuildings++;
@@ -1167,7 +1760,7 @@ CRenderer::ScanSectorList(CPtrList *lists)
if(IsEntityCullZoneVisible(ent)){
switch(SetupEntityVisibility(ent)){
case VIS_VISIBLE:
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ InsertEntityIntoList(ent);
break;
case VIS_INVISIBLE:
if(!IsGlass(ent->GetModelIndex()))
@@ -1210,7 +1803,7 @@ CRenderer::ScanSectorList(CPtrList *lists)
break;
}
#endif
- }else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable() && !CStreaming::ms_disableStreaming){
+ }else if(IsRoad(ent) && !CStreaming::ms_disableStreaming){
if(SetupEntityVisibility(ent) == VIS_STREAMME)
if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)
CStreaming::RequestModel(ent->GetModelIndex(), 0);
@@ -1243,7 +1836,7 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists)
if(IsEntityCullZoneVisible(ent)){
switch(SetupEntityVisibility(ent)){
case VIS_VISIBLE:
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ InsertEntityIntoList(ent);
break;
case VIS_INVISIBLE:
if(!IsGlass(ent->GetModelIndex()))
@@ -1289,7 +1882,7 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists)
break;
}
#endif
- }else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable() && !CStreaming::ms_disableStreaming){
+ }else if(IsRoad(ent) && !CStreaming::ms_disableStreaming){
if(SetupEntityVisibility(ent) == VIS_STREAMME)
CStreaming::RequestModel(ent->GetModelIndex(), 0);
}else{
@@ -1320,7 +1913,7 @@ CRenderer::ScanSectorList_Subway(CPtrList *lists)
ent->m_scanCode = CWorld::GetCurrentScanCode();
switch(SetupEntityVisibility(ent)){
case VIS_VISIBLE:
- ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
+ InsertEntityIntoList(ent);
break;
case VIS_OFFSCREEN:
dx = ms_vecCameraPosition.x - ent->GetPosition().x;
diff --git a/src/render/Renderer.h b/src/render/Renderer.h
index e14f73b1..35b43a0b 100644
--- a/src/render/Renderer.h
+++ b/src/render/Renderer.h
@@ -40,6 +40,13 @@ class CRenderer
static CEntity *ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES];
static int32 ms_nNoOfInVisibleEntities;
static CEntity *ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES];
+#ifdef NEW_RENDERER
+ static int32 ms_nNoOfVisibleVehicles;
+ static CEntity *ms_aVisibleVehiclePtrs[NUMVISIBLEENTITIES];
+ // for cWorldStream emulation
+ static int32 ms_nNoOfVisibleBuildings;
+ static CEntity *ms_aVisibleBuildingPtrs[NUMVISIBLEENTITIES];
+#endif
static CVector ms_vecCameraPosition;
static CVehicle *m_pFirstPersonVehicle;
@@ -90,4 +97,15 @@ public:
static bool IsVehicleCullZoneVisible(CEntity *ent);
static void RemoveVehiclePedLights(CEntity *ent, bool reset);
+
+
+#ifdef NEW_RENDERER
+ static void ClearForFrame(void);
+ static void RenderPeds(void);
+ static void RenderVehicles(void); // also renders peds in LCS
+ static void RenderOneBuilding(CEntity *ent, float camdist = 0.0f);
+ static void RenderWorld(int pass); // like cWorldStream::Render(int)
+ static void RenderWater(void); // keep-out polys and water
+#endif
+ static void InsertEntityIntoList(CEntity *ent);
};
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index ade5db81..4ad06543 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -141,6 +141,9 @@ CSpecialFX::Render(void)
CBrightLights::Render();
CShinyTexts::Render();
CMoneyMessages::Render();
+#ifdef NEW_RENDERER
+ if(!(gbNewRenderer && FredIsInFirstPersonCam()))
+#endif
C3dMarkers::Render();
}
@@ -1091,21 +1094,25 @@ CMoneyMessages::Render()
void
CMoneyMessages::RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity)
{
- uint32 nIndex = 0;
- while (aMoneyMessages[nIndex].m_nTimeRegistered != 0) {
- if (++nIndex >= NUMMONEYMESSAGES) return;
- }
-
- // Add data of this money message to the array
- AsciiToUnicode(pText, aMoneyMessages[nIndex].m_aText);
+ uint32 i;
+#ifdef FIX_BUGS
+ for(i = 0; i < NUMMONEYMESSAGES && aMoneyMessages[i].m_nTimeRegistered != 0; i++);
+#else
+ for(i = 0; aMoneyMessages[i].m_nTimeRegistered != 0 && i < NUMMONEYMESSAGES; i++);
+#endif
- aMoneyMessages[nIndex].m_nTimeRegistered = CTimer::GetTimeInMilliseconds();
- aMoneyMessages[nIndex].m_vecPosition = vecPos;
- aMoneyMessages[nIndex].m_Colour.red = bRed;
- aMoneyMessages[nIndex].m_Colour.green = bGreen;
- aMoneyMessages[nIndex].m_Colour.blue = bBlue;
- aMoneyMessages[nIndex].m_fSize = fSize;
- aMoneyMessages[nIndex].m_fOpacity = fOpacity;
+ if(i < NUMMONEYMESSAGES) {
+ // Add data of this money message to the array
+ AsciiToUnicode(pText, aMoneyMessages[i].m_aText);
+
+ aMoneyMessages[i].m_nTimeRegistered = CTimer::GetTimeInMilliseconds();
+ aMoneyMessages[i].m_vecPosition = vecPos;
+ aMoneyMessages[i].m_Colour.red = bRed;
+ aMoneyMessages[i].m_Colour.green = bGreen;
+ aMoneyMessages[i].m_Colour.blue = bBlue;
+ aMoneyMessages[i].m_fSize = fSize;
+ aMoneyMessages[i].m_fOpacity = fOpacity;
+ }
}
CRGBA FoamColour(255, 255, 255, 255);
diff --git a/src/render/WaterLevel.cpp b/src/render/WaterLevel.cpp
index a0c7ae31..7aa01f5a 100644
--- a/src/render/WaterLevel.cpp
+++ b/src/render/WaterLevel.cpp
@@ -37,7 +37,7 @@ bool CWaterLevel::WavesCalculatedThisFrame;
RpAtomic *CWaterLevel::ms_pWavyAtomic;
RpGeometry *CWaterLevel::apGeomArray[8];
int16 CWaterLevel::nGeomUsed;
-//"Custom" Donīt Render Water Toggle
+//"Custom" Don't Render Water Toggle
bool gbDontRenderWater;
//RwTexture *gpWaterTex;
@@ -638,7 +638,7 @@ SectorRadius(float fSize)
void
CWaterLevel::RenderWater()
{
-//"Custom" Donīt Render Water Toggle
+//"Custom" Don't Render Water Toggle
#ifndef MASTER
if (gbDontRenderWater)
return;
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index bf3e51b4..771f85de 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -202,6 +202,7 @@ void CWeather::Update(void)
}
// Rain
+#ifndef VC_RAIN_NERF
float fNewRain;
if (NewWeatherType == WEATHER_RAINY) {
// if raining for >1 hour, values: 0, 0.33, 0.66, 0.99, switching every ~16.5s
@@ -223,6 +224,25 @@ void CWeather::Update(void)
else
Rain = Max(fNewRain, Rain - RAIN_CHANGE_SPEED * CTimer::GetTimeStep());
}
+#else
+ float fNewRain;
+ if (NewWeatherType == WEATHER_RAINY) {
+ // if raining for >1 hour, values: 0, 0.33, switching every ~16.5s
+ fNewRain = (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.33f;
+ if (OldWeatherType != WEATHER_RAINY) {
+ if (InterpolationValue < 0.4f)
+ // if rain has just started (<24 minutes), always 0.5
+ fNewRain = 0.5f;
+ else
+ // if rain is ongoing for >24 minutes, values: 0.25, 0.5, switching every ~16.5s
+ fNewRain = 0.25f + (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.25f;
+ }
+ fNewRain = Max(fNewRain, 0.5f);
+ }
+ else
+ fNewRain = 0.0f;
+ Rain = fNewRain;
+#endif
// Clouds
if (OldWeatherType != WEATHER_SUNNY)