diff options
Diffstat (limited to 'src/render/Renderer.cpp')
-rw-r--r-- | src/render/Renderer.cpp | 515 |
1 files changed, 196 insertions, 319 deletions
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 660b05fe..5c65eea5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2,6 +2,7 @@ #include "common.h" #include "main.h" +#include "General.h" #include "Lights.h" #include "ModelInfo.h" #include "Treadable.h" @@ -20,6 +21,7 @@ #include "ModelIndices.h" #include "Streaming.h" #include "Shadows.h" +#include "Coronas.h" #include "PointLights.h" #include "Occlusion.h" #include "Renderer.h" @@ -40,6 +42,8 @@ bool gbDontRenderPeds; bool gbDontRenderObjects; bool gbDontRenderVehicles; +bool gbRenderDebugEnvMap; + // unused int16 TestCloseThings; int16 TestBigThings; @@ -347,8 +351,6 @@ enum { PASS_BLEND // normal blend }; -static RwRGBAReal black; - static void SetStencilState(int state) { @@ -377,314 +379,6 @@ SetStencilState(int state) } } -#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) { @@ -715,16 +409,16 @@ CRenderer::RenderOneBuilding(CEntity *ent, float camdist) alpha = mi->m_alpha * fadefactor; if(alpha == 255) - AtomicFirstPass(atomic, pass); + WorldRender::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); + WorldRender::AtomicFullyTransparent(atomic, pass, alpha); } }else - AtomicFirstPass(atomic, pass); + WorldRender::AtomicFirstPass(atomic, pass); ent->bImBeingRendered = false; // TODO: this seems wrong, but do we even need it? } @@ -779,16 +473,16 @@ CRenderer::RenderWorld(int pass) RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); - RenderBlendPass(PASS_NOZ); + WorldRender::RenderBlendPass(PASS_NOZ); RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); break; case 2: // Transparent RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); - RenderBlendPass(PASS_ADD); + WorldRender::RenderBlendPass(PASS_ADD); RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RenderBlendPass(PASS_BLEND); + WorldRender::RenderBlendPass(PASS_BLEND); break; } } @@ -872,9 +566,9 @@ CRenderer::ClearForFrame(void) ms_nNoOfInVisibleEntities = 0; gSortedVehiclesAndPeds.Clear(); - numBlendInsts[PASS_NOZ] = 0; - numBlendInsts[PASS_ADD] = 0; - numBlendInsts[PASS_BLEND] = 0; + WorldRender::numBlendInsts[PASS_NOZ] = 0; + WorldRender::numBlendInsts[PASS_ADD] = 0; + WorldRender::numBlendInsts[PASS_BLEND] = 0; } #endif @@ -1952,3 +1646,186 @@ CRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset) SetAmbientColours(); DeActivateDirectional(); } + + +#include "postfx.h" + +static RwIm2DVertex Screen2EnvQuad[4]; +static RwImVertexIndex EnvQuadIndices[6] = { 0, 1, 2, 0, 2, 3 }; + +static void +SetQuadVertices(RwRaster *env, RwRaster *screen, float z) +{ + uint32 width = RwRasterGetWidth(env); + uint32 height = RwRasterGetHeight(env); + + float zero, xmax, ymax; + + zero = -HALFPX; + xmax = width - HALFPX; + ymax = height - HALFPX; + + float recipz = 1.0f/z; + float umax = (float)SCREEN_WIDTH/RwRasterGetWidth(screen); + float vmax = (float)SCREEN_HEIGHT/RwRasterGetHeight(screen); + + RwIm2DVertexSetScreenX(&Screen2EnvQuad[0], zero); + RwIm2DVertexSetScreenY(&Screen2EnvQuad[0], zero); + RwIm2DVertexSetScreenZ(&Screen2EnvQuad[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&Screen2EnvQuad[0], z); + RwIm2DVertexSetRecipCameraZ(&Screen2EnvQuad[0], recipz); + RwIm2DVertexSetU(&Screen2EnvQuad[0], 0.0f, recipz); + RwIm2DVertexSetV(&Screen2EnvQuad[0], 0.0f, recipz); + RwIm2DVertexSetIntRGBA(&Screen2EnvQuad[0], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&Screen2EnvQuad[1], zero); + RwIm2DVertexSetScreenY(&Screen2EnvQuad[1], ymax); + RwIm2DVertexSetScreenZ(&Screen2EnvQuad[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&Screen2EnvQuad[1], z); + RwIm2DVertexSetRecipCameraZ(&Screen2EnvQuad[1], recipz); + RwIm2DVertexSetU(&Screen2EnvQuad[1], 0.0f, recipz); + RwIm2DVertexSetV(&Screen2EnvQuad[1], vmax, recipz); + RwIm2DVertexSetIntRGBA(&Screen2EnvQuad[1], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&Screen2EnvQuad[2], xmax); + RwIm2DVertexSetScreenY(&Screen2EnvQuad[2], ymax); + RwIm2DVertexSetScreenZ(&Screen2EnvQuad[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&Screen2EnvQuad[2], z); + RwIm2DVertexSetRecipCameraZ(&Screen2EnvQuad[2], recipz); + RwIm2DVertexSetU(&Screen2EnvQuad[2], umax, recipz); + RwIm2DVertexSetV(&Screen2EnvQuad[2], vmax, recipz); + RwIm2DVertexSetIntRGBA(&Screen2EnvQuad[2], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&Screen2EnvQuad[3], xmax); + RwIm2DVertexSetScreenY(&Screen2EnvQuad[3], zero); + RwIm2DVertexSetScreenZ(&Screen2EnvQuad[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetCameraZ(&Screen2EnvQuad[3], z); + RwIm2DVertexSetRecipCameraZ(&Screen2EnvQuad[3], recipz); + RwIm2DVertexSetU(&Screen2EnvQuad[3], umax, recipz); + RwIm2DVertexSetV(&Screen2EnvQuad[3], 0.0f, recipz); + RwIm2DVertexSetIntRGBA(&Screen2EnvQuad[3], 255, 255, 255, 255); +} + +static RwIm2DVertex coronaVerts[4*4]; +static RwImVertexIndex coronaIndices[6*4]; +static int numCoronaVerts, numCoronaIndices; + +static void +AddCorona(float x, float y, float sz) +{ + float nearz, recipz; + RwIm2DVertex *v; + nearz = RwIm2DGetNearScreenZ(); + float z = RwCameraGetNearClipPlane(RwCameraGetCurrentCamera()); + recipz = 1.0f/z; + + v = &coronaVerts[numCoronaVerts]; + RwIm2DVertexSetScreenX(&v[0], x); + RwIm2DVertexSetScreenY(&v[0], y); + RwIm2DVertexSetScreenZ(&v[0], z); + RwIm2DVertexSetScreenZ(&v[0], nearz); + RwIm2DVertexSetRecipCameraZ(&v[0], recipz); + RwIm2DVertexSetU(&v[0], 0.0f, recipz); + RwIm2DVertexSetV(&v[0], 0.0f, recipz); + RwIm2DVertexSetIntRGBA(&v[0], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&v[1], x); + RwIm2DVertexSetScreenY(&v[1], y + sz); + RwIm2DVertexSetScreenZ(&v[1], z); + RwIm2DVertexSetScreenZ(&v[1], nearz); + RwIm2DVertexSetRecipCameraZ(&v[1], recipz); + RwIm2DVertexSetU(&v[1], 0.0f, recipz); + RwIm2DVertexSetV(&v[1], 1.0f, recipz); + RwIm2DVertexSetIntRGBA(&v[1], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&v[2], x + sz); + RwIm2DVertexSetScreenY(&v[2], y + sz); + RwIm2DVertexSetScreenZ(&v[2], z); + RwIm2DVertexSetScreenZ(&v[2], nearz); + RwIm2DVertexSetRecipCameraZ(&v[2], recipz); + RwIm2DVertexSetU(&v[2], 1.0f, recipz); + RwIm2DVertexSetV(&v[2], 1.0f, recipz); + RwIm2DVertexSetIntRGBA(&v[2], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX(&v[3], x + sz); + RwIm2DVertexSetScreenY(&v[3], y); + RwIm2DVertexSetScreenZ(&v[3], z); + RwIm2DVertexSetScreenZ(&v[3], nearz); + RwIm2DVertexSetRecipCameraZ(&v[3], recipz); + RwIm2DVertexSetU(&v[3], 1.0f, recipz); + RwIm2DVertexSetV(&v[3], 0.0f, recipz); + RwIm2DVertexSetIntRGBA(&v[3], 255, 255, 255, 255); + + + coronaIndices[numCoronaIndices++] = numCoronaVerts; + coronaIndices[numCoronaIndices++] = numCoronaVerts + 1; + coronaIndices[numCoronaIndices++] = numCoronaVerts + 2; + coronaIndices[numCoronaIndices++] = numCoronaVerts; + coronaIndices[numCoronaIndices++] = numCoronaVerts + 2; + coronaIndices[numCoronaIndices++] = numCoronaVerts + 3; + numCoronaVerts += 4; +} +#include "Debug.h" + +static void +DrawEnvMapCoronas(float heading) +{ + RwRaster *rt = RwTextureGetRaster(CustomPipes::EnvMapTex); + const float BIG = 89.0f * RwRasterGetWidth(rt)/128.0f; + const float SMALL = 38.0f * RwRasterGetHeight(rt)/128.0f; + + float x; + numCoronaVerts = 0; + numCoronaIndices = 0; + x = (heading - PI)/TWOPI;// - 1.0f; + x *= BIG+SMALL; + AddCorona(x, 0.0f, BIG); x += BIG; + AddCorona(x, 12.0f, SMALL); x += SMALL; + AddCorona(x, 0.0f, BIG); x += BIG; + AddCorona(x, 12.0f, SMALL); x += SMALL; + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[CCoronas::TYPE_STAR])); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, coronaVerts, numCoronaVerts, coronaIndices, numCoronaIndices); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); +} + +void +CRenderer::GenerateEnvironmentMap(void) +{ + // We'll probably do this differently eventually + // re-using all sorts of stuff here... + + CPostFX::GetBackBuffer(Scene.camera); + + RwCameraBeginUpdate(CustomPipes::EnvMapCam); + + // get current scene + SetQuadVertices(RwTextureGetRaster(CustomPipes::EnvMapTex), CPostFX::pBackBuffer, RwCameraGetNearClipPlane(RwCameraGetCurrentCamera())); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, CPostFX::pBackBuffer); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Screen2EnvQuad, 4, EnvQuadIndices, 6); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + + // Draw coronas + if(CustomPipes::VehiclePipeSwitch != CustomPipes::VEHICLEPIPE_MOBILE) + DrawEnvMapCoronas(TheCamera.GetForward().Heading()); + + RwCameraEndUpdate(CustomPipes::EnvMapCam); + + + RwCameraBeginUpdate(Scene.camera); + + if(gbRenderDebugEnvMap){ + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(CustomPipes::EnvMapTex)); + RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, CustomPipes::EnvScreenQuad, 4, (RwImVertexIndex*)CustomPipes::QuadIndices, 6); + } +} |