diff options
| author | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
|---|---|---|
| committer | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
| commit | b691c43c44ff180d10e7d4a9afc83b98551ff586 (patch) | |
| tree | 3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/GameRenderer.cpp | |
| parent | def8cb415354ac390b7e89052a50605285f1aca9 (diff) | |
Initial commit
Diffstat (limited to 'Minecraft.Client/GameRenderer.cpp')
| -rw-r--r-- | Minecraft.Client/GameRenderer.cpp | 2169 |
1 files changed, 2169 insertions, 0 deletions
diff --git a/Minecraft.Client/GameRenderer.cpp b/Minecraft.Client/GameRenderer.cpp new file mode 100644 index 00000000..508b3a1a --- /dev/null +++ b/Minecraft.Client/GameRenderer.cpp @@ -0,0 +1,2169 @@ +#include "stdafx.h" +#include "GameRenderer.h" +#include "ItemInHandRenderer.h" +#include "LevelRenderer.h" +#include "Frustum.h" +#include "FrustumCuller.h" +#include "Textures.h" +#include "Tesselator.h" +#include "ParticleEngine.h" +#include "SmokeParticle.h" +#include "WaterDropParticle.h" +#include "GameMode.h" +#include "CreativeMode.h" +#include "Lighting.h" +#include "Options.h" +#include "MultiplayerLocalPlayer.h" +#include "GuiParticles.h" +#include "MultiPlayerLevel.h" +#include "Chunk.h" +#include "..\Minecraft.World\net.minecraft.world.entity.h" +#include "..\Minecraft.World\net.minecraft.world.level.h" +#include "..\Minecraft.World\net.minecraft.world.entity.player.h" +#include "..\Minecraft.World\net.minecraft.world.phys.h" +#include "..\Minecraft.World\net.minecraft.world.level.material.h" +#include "..\Minecraft.World\net.minecraft.world.level.tile.h" +#include "..\Minecraft.World\net.minecraft.world.level.chunk.h" +#include "..\Minecraft.World\net.minecraft.world.level.biome.h" +#include "..\Minecraft.World\net.minecraft.world.level.dimension.h" +#include "..\Minecraft.World\System.h" +#include "..\Minecraft.World\FloatBuffer.h" +#include "..\Minecraft.World\ThreadName.h" +#include "..\Minecraft.World\SparseLightStorage.h" +#include "..\Minecraft.World\CompressedTileStorage.h" +#include "..\Minecraft.World\SparseDataStorage.h" +#include "..\Minecraft.World\JavaMath.h" +#include "..\Minecraft.World\Facing.h" +#include "..\Minecraft.World\MobEffect.h" +#include "..\Minecraft.World\IntCache.h" +#include "..\Minecraft.World\SmoothFloat.h" +#include "..\Minecraft.World\MobEffectInstance.h" +#include "..\Minecraft.World\Item.h" +#include "Camera.h" +#include "..\Minecraft.World\SoundTypes.h" +#include "HumanoidModel.h" +#include "..\Minecraft.World\Item.h" +#include "..\Minecraft.World\compression.h" +#include "PS3\PS3Extras\ShutdownManager.h" + +#include "TexturePackRepository.h" +#include "TexturePack.h" + +bool GameRenderer::anaglyph3d = false; +int GameRenderer::anaglyphPass = 0; + +#ifdef MULTITHREAD_ENABLE +C4JThread* GameRenderer::m_updateThread; +C4JThread::EventArray* GameRenderer::m_updateEvents; +bool GameRenderer::nearThingsToDo = false; +bool GameRenderer::updateRunning = false; +vector<byte *> GameRenderer::m_deleteStackByte; +vector<SparseLightStorage *> GameRenderer::m_deleteStackSparseLightStorage; +vector<CompressedTileStorage *> GameRenderer::m_deleteStackCompressedTileStorage; +vector<SparseDataStorage *> GameRenderer::m_deleteStackSparseDataStorage; +#endif +CRITICAL_SECTION GameRenderer::m_csDeleteStack; + +GameRenderer::GameRenderer(Minecraft *mc) +{ + // 4J - added this block of initialisers + renderDistance = 0; + _tick = 0; + hovered = nullptr; + thirdDistance = 4; + thirdDistanceO = 4; + thirdRotation = 0; + thirdRotationO = 0; + thirdTilt = 0; + thirdTiltO = 0; + + accumulatedSmoothXO = 0; + accumulatedSmoothYO = 0; + tickSmoothXO = 0; + tickSmoothYO = 0; + lastTickA = 0; + + cameraPos = Vec3::newPermanent(0.0f,0.0f,0.0f); + + fovOffset = 0; + fovOffsetO = 0; + cameraRoll = 0; + cameraRollO = 0; + for( int i = 0; i < 4; i++ ) + { + fov[i] = 0.0f; + oFov[i] = 0.0f; + tFov[i] = 0.0f; + } + isInClouds = false; + zoom = 1; + zoom_x = 0; + zoom_y = 0; + rainXa = NULL; + rainZa = NULL; + lastActiveTime = Minecraft::currentTimeMillis(); + lastNsTime = 0; + random = new Random(); + rainSoundTime = 0; + xMod = 0; + yMod = 0; + lb = MemoryTracker::createFloatBuffer(16); + fr = 0.0f; + fg = 0.0f; + fb = 0.0f; + fogBrO = 0.0f; + fogBr = 0.0f; + cameraFlip = 0; + _updateLightTexture = false; + blr = 0.0f; + blrt = 0.0f; + blg = 0.0f; + blgt = 0.0f; + + + m_fov=70.0f; + + // 4J Stu - Init these so they are setup before the tick + for( int i = 0; i < 4; i++ ) + { + fov[i] = oFov[i] = 1.0f; + } + + this->mc = mc; + itemInHandRenderer = NULL; + + // 4J-PB - set up the local players iteminhand renderers here - needs to be done with lighting enabled so that the render geometry gets compiled correctly + glEnable(GL_LIGHTING); + mc->localitemInHandRenderers[0] = new ItemInHandRenderer(mc);//itemInHandRenderer; + mc->localitemInHandRenderers[1] = new ItemInHandRenderer(mc); + mc->localitemInHandRenderers[2] = new ItemInHandRenderer(mc); + mc->localitemInHandRenderers[3] = new ItemInHandRenderer(mc); + glDisable(GL_LIGHTING); + + // 4J - changes brought forward from 1.8.2 + BufferedImage *img = new BufferedImage(16, 16, BufferedImage::TYPE_INT_RGB); + for( int i = 0; i < NUM_LIGHT_TEXTURES; i++ ) + { + lightTexture[i] = mc->textures->getTexture(img); // 4J - changed to one light texture per level to support split screen + } + delete img; +#ifdef __PS3__ + // we're using the RSX now to upload textures to vram, so we need the main ram textures allocated from io space + for(int i=0;i<NUM_LIGHT_TEXTURES;i++) + lightPixels[i] = intArray((int*)RenderManager.allocIOMem(16*16*sizeof(int)), 16*16); +#else + for(int i=0;i<NUM_LIGHT_TEXTURES;i++) + lightPixels[i] = intArray(16*16); +#endif + +#ifdef MULTITHREAD_ENABLE + m_updateEvents = new C4JThread::EventArray(eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear); + m_updateEvents->Set(eUpdateEventIsFinished); + + InitializeCriticalSection(&m_csDeleteStack); + m_updateThread = new C4JThread(runUpdate, NULL, "Chunk update"); +#ifdef __PS3__ + m_updateThread->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); +#endif// __PS3__ + m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE); + m_updateThread->Run(); +#endif +} + +// 4J Stu Added to go with 1.8.2 change +GameRenderer::~GameRenderer() +{ + if(rainXa != NULL) delete [] rainXa; + if(rainZa != NULL) delete [] rainZa; +} + +void GameRenderer::tick(bool first) // 4J - add bFirst +{ + tickFov(); + tickLightTexture(); // 4J - change brought forward from 1.8.2 + fogBrO = fogBr; + thirdDistanceO = thirdDistance; + thirdRotationO = thirdRotation; + thirdTiltO = thirdTilt; + fovOffsetO = fovOffset; + cameraRollO = cameraRoll; + + if (ClientConstants::DEADMAU5_CAMERA_CHEATS) + { + if (mc->screen == NULL) + { + float distanceDelta = 0; + float rotationDelta = 0; + float tiltDelta = 0; + float rollDelta = 0; + + if (Keyboard::isKeyDown(Keyboard::KEY_U)) + { + distanceDelta -= .3f * mc->options->cameraSpeed; + } + else if (Keyboard::isKeyDown(Keyboard::KEY_O)) + { + distanceDelta += .3f * mc->options->cameraSpeed; + } + if (Keyboard::isKeyDown(Keyboard::KEY_J)) + { + rotationDelta += 8.0f * mc->options->cameraSpeed; + } + else if (Keyboard::isKeyDown(Keyboard::KEY_L)) + { + rotationDelta -= 8.0f * mc->options->cameraSpeed; + } + if (Keyboard::isKeyDown(Keyboard::KEY_I)) + { + tiltDelta += 6.0f * mc->options->cameraSpeed; + } + else if (Keyboard::isKeyDown(Keyboard::KEY_K)) + { + tiltDelta -= 6.0f * mc->options->cameraSpeed; + } + if (Keyboard::isKeyDown(Keyboard::KEY_Y) && Keyboard::isKeyDown(Keyboard::KEY_H)) + { + fovOffset = 0; + } + else if (Keyboard::isKeyDown(Keyboard::KEY_Y)) + { + fovOffset -= 3.0f; + } + else if (Keyboard::isKeyDown(Keyboard::KEY_H)) + { + fovOffset += 3.0f; + } + if (Keyboard::isKeyDown(Keyboard::KEY_N) && Keyboard::isKeyDown(Keyboard::KEY_M)) + { + cameraRoll = 0; + } + else if (Keyboard::isKeyDown(Keyboard::KEY_N)) + { + rollDelta -= 8.0f * mc->options->cameraSpeed; + } + else if (Keyboard::isKeyDown(Keyboard::KEY_M)) + { + rollDelta += 8.0f * mc->options->cameraSpeed; + } + + if (mc->options->smoothCamera) + { + distanceDelta = smoothDistance.getNewDeltaValue(distanceDelta, .5f * mc->options->sensitivity); + rotationDelta = smoothRotation.getNewDeltaValue(rotationDelta, .5f * mc->options->sensitivity); + tiltDelta = smoothTilt.getNewDeltaValue(tiltDelta, .5f * mc->options->sensitivity); + rollDelta = smoothRoll.getNewDeltaValue(rollDelta, .5f * mc->options->sensitivity); + } + thirdDistance += distanceDelta; + thirdRotation += rotationDelta; + thirdTilt += tiltDelta; + cameraRoll += rollDelta; + } + } + + if (mc->options->smoothCamera) + { + // update player view in tick() instead of render() to maintain +// camera movement regardless of FPS + float ss = mc->options->sensitivity * 0.6f + 0.2f; + float sens = (ss * ss * ss) * 8; + tickSmoothXO = smoothTurnX.getNewDeltaValue(accumulatedSmoothXO, 0.05f * sens); + tickSmoothYO = smoothTurnY.getNewDeltaValue(accumulatedSmoothYO, 0.05f * sens); + lastTickA = 0; + + accumulatedSmoothXO = 0; + accumulatedSmoothYO = 0; + } + + if (mc->cameraTargetPlayer == NULL) + { + mc->cameraTargetPlayer = dynamic_pointer_cast<Mob>(mc->player); + } + + float brr = mc->level->getBrightness(Mth::floor(mc->cameraTargetPlayer->x), Mth::floor(mc->cameraTargetPlayer->y), Mth::floor(mc->cameraTargetPlayer->z)); + float whiteness = (3 - mc->options->viewDistance) / 3.0f; + float fogBrT = brr * (1 - whiteness) + whiteness; + fogBr += (fogBrT - fogBr) * 0.1f; + + itemInHandRenderer->tick(); + + PIXBeginNamedEvent(0,"Rain tick"); + tickRain(); + PIXEndNamedEvent(); + + if( mc->player != mc->localplayers[ProfileManager.GetPrimaryPad()] ) return; // 4J added for split screen - only do rest of processing for once per frame + + _tick++; +} + +void GameRenderer::pick(float a) +{ + if (mc->cameraTargetPlayer == NULL) return; + if (mc->level == NULL) return; + + double range = mc->gameMode->getPickRange(); + delete mc->hitResult; + MemSect(31); + mc->hitResult = mc->cameraTargetPlayer->pick(range, a); + MemSect(0); + + // 4J - added - stop blocks right at the edge of the world from being pickable so we shouldn't be able to directly destroy or create anything there + if( mc->hitResult ) + { + int maxxz = ( ( mc->level->chunkSource->m_XZSize / 2 ) * 16 ) - 2; + int minxz = ( -( mc->level->chunkSource->m_XZSize / 2 ) * 16 ) + 1; + + // Don't select the tops of the very edge blocks, or the sides of the next blocks in + // 4J Stu - Only block the sides that are facing an outside block + int hitx = mc->hitResult->x; + int hitz = mc->hitResult->z; + int face = mc->hitResult->f; + if( face == Facing::WEST && hitx < 0 ) hitx -= 1; + if( face == Facing::EAST && hitx > 0 ) hitx += 1; + if( face == Facing::NORTH && hitz < 0 ) hitz -= 1; + if( face == Facing::SOUTH && hitz > 0 ) hitz += 1; + + if( ( hitx < minxz ) || ( hitx > maxxz) || + ( hitz < minxz ) || ( hitz > maxxz) ) + { + delete mc->hitResult; + mc->hitResult = NULL; + } + } + + double dist = range; + Vec3 *from = mc->cameraTargetPlayer->getPos(a); + + if (mc->gameMode->hasFarPickRange()) + { + dist = range = 6; + } + else + { + if (dist > 3) dist = 3; + range = dist; + } + + if (mc->hitResult != NULL) + { + dist = mc->hitResult->pos->distanceTo(from); + } + + Vec3 *b = mc->cameraTargetPlayer->getViewVector(a); + Vec3 *to = from->add(b->x * range, b->y * range, b->z * range); + hovered = nullptr; + float overlap = 1; + vector<shared_ptr<Entity> > *objects = mc->level->getEntities(mc->cameraTargetPlayer, mc->cameraTargetPlayer->bb->expand(b->x * (range), b->y * (range), b->z * (range))->grow(overlap, overlap, overlap)); + double nearest = dist; + + AUTO_VAR(itEnd, objects->end()); + for (AUTO_VAR(it, objects->begin()); it != itEnd; it++) + { + shared_ptr<Entity> e = *it; //objects->at(i); + if (!e->isPickable()) continue; + + float rr = e->getPickRadius(); + AABB *bb = e->bb->grow(rr, rr, rr); + HitResult *p = bb->clip(from, to); + if (bb->contains(from)) + { + if (0 < nearest || nearest == 0) + { + hovered = e; + nearest = 0; + } + } + else if (p != NULL) + { + double dd = from->distanceTo(p->pos); + if (dd < nearest || nearest == 0) + { + hovered = e; + nearest = dd; + } + } + delete p; + } + + if (hovered != NULL) + { + if (nearest < dist || (mc->hitResult == NULL)) + { + if( mc->hitResult != NULL ) + delete mc->hitResult; + mc->hitResult = new HitResult(hovered); + } + } +} + +void GameRenderer::SetFovVal(float fov) +{ + m_fov=fov; +} + +float GameRenderer::GetFovVal() +{ + return m_fov; +} + +void GameRenderer::tickFov() +{ + shared_ptr<LocalPlayer>player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer); + + int playerIdx = player ? player->GetXboxPad() : 0; + tFov[playerIdx] = player->getFieldOfViewModifier(); + + oFov[playerIdx] = fov[playerIdx]; + fov[playerIdx] += (tFov[playerIdx] - fov[playerIdx]) * 0.5f; +} + +float GameRenderer::getFov(float a, bool applyEffects) +{ + if (cameraFlip > 0 ) return 90; + + shared_ptr<LocalPlayer> player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer); + int playerIdx = player ? player->GetXboxPad() : 0; + float fov = m_fov;//70; + if (applyEffects) + { + fov += mc->options->fov * 40; + fov *= this->oFov[playerIdx] + (this->fov[playerIdx] - this->oFov[playerIdx]) * a; + } + if (player->getHealth() <= 0) + { + float duration = player->deathTime + a; + + fov /= ((1 - 500 / (duration + 500)) * 2.0f + 1); + } + + int t = Camera::getBlockAt(mc->level, player, a); + if (t != 0 && Tile::tiles[t]->material == Material::water) fov = fov * 60 / 70; + + return fov + fovOffsetO + (fovOffset - fovOffsetO) * a; + +} + +void GameRenderer::bobHurt(float a) +{ + shared_ptr<Mob> player = mc->cameraTargetPlayer; + + float hurt = player->hurtTime - a; + + if (player->getHealth() <= 0) + { + float duration = player->deathTime + a; + + glRotatef(40 - (40 * 200) / (duration + 200), 0, 0, 1); + } + + if (hurt < 0) return; + hurt /= player->hurtDuration; + hurt = (float) Mth::sin(hurt * hurt * hurt * hurt * PI); + + float rr = player->hurtDir; + + + glRotatef(-rr, 0, 1, 0); + glRotatef(-hurt * 14, 0, 0, 1); + glRotatef(+rr, 0, 1, 0); + +} + +void GameRenderer::bobView(float a) +{ + shared_ptr<Player> player = dynamic_pointer_cast<Player>(mc->cameraTargetPlayer); + if(player==NULL) + { + return; + } + //shared_ptr<Player> player = dynamic_pointer_cast<Player>(mc->cameraTargetPlayer); + + float wda = player->walkDist - player->walkDistO; + float b = -(player->walkDist + wda * a); + float bob = player->oBob + (player->bob - player->oBob) * a; + float tilt = player->oTilt + (player->tilt - player->oTilt) * a; + glTranslatef((float) Mth::sin(b * PI) * bob * 0.5f, -(float) abs(Mth::cos(b * PI) * bob), 0); + glRotatef((float) Mth::sin(b * PI) * bob * 3, 0, 0, 1); + glRotatef((float) abs(Mth::cos(b * PI - 0.2f) * bob) * 5, 1, 0, 0); + glRotatef((float) tilt, 1, 0, 0); +} + +void GameRenderer::moveCameraToPlayer(float a) +{ + shared_ptr<Mob> player = mc->cameraTargetPlayer; + shared_ptr<LocalPlayer> localplayer = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer); + float heightOffset = player->heightOffset - 1.62f; + + double x = player->xo + (player->x - player->xo) * a; + double y = player->yo + (player->y - player->yo) * a - heightOffset; + double z = player->zo + (player->z - player->zo) * a; + + + glRotatef(cameraRollO + (cameraRoll - cameraRollO) * a, 0, 0, 1); + + if (player->isSleeping()) + { + heightOffset += 1.0; + glTranslatef(0.0f, 0.3f, 0); + if (!mc->options->fixedCamera) + { + int t = mc->level->getTile(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z)); + if (t == Tile::bed_Id) + { + int data = mc->level->getData(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z)); + + int direction = data & 3; + glRotatef((float)direction * 90,0.0f, 1.0f, 0.0f); + } + glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, -1, 0); + glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, -1, 0, 0); + } + } + // 4J-PB - changing this to be per player + //else if (mc->options->thirdPersonView) + else if (localplayer->ThirdPersonView()) + { + double cameraDist = thirdDistanceO + (thirdDistance - thirdDistanceO) * a; + + if (mc->options->fixedCamera) + { + + float rotationY = thirdRotationO + (thirdRotation - thirdRotationO) * a; + float xRot = thirdTiltO + (thirdTilt - thirdTiltO) * a; + + glTranslatef(0, 0, (float) -cameraDist); + glRotatef(xRot, 1, 0, 0); + glRotatef(rotationY, 0, 1, 0); + } + else + { + // 4J - corrected bug where this used to just take player->xRot & yRot directly and so wasn't taking into account interpolation, allowing camera to go through walls + float yRot = player->yRotO + (player->yRot - player->yRotO) * a; + float xRot = player->xRotO + (player->xRot - player->xRotO) * a; + + // Thirdperson view values are now 0 for disabled, 1 for original mode, 2 for reversed. + if( localplayer->ThirdPersonView() == 2 ) + { + // Reverse y rotation - note that this is only used in doing collision to calculate our view + // distance, the actual rotation itself is just below this else {} block + yRot += 180.0f; + } + + double xd = -Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist; + double zd = Mth::cos(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist; + double yd = -Mth::sin(xRot / 180 * PI) * cameraDist; + + for (int i = 0; i < 8; i++) + { + float xo = (float)((i & 1) * 2 - 1); + float yo = (float)(((i >> 1) & 1) * 2 - 1); + float zo = (float)(((i >> 2) & 1) * 2 - 1); + + xo *= 0.1f; + yo *= 0.1f; + zo *= 0.1f; + + // 4J - corrected bug here where zo was also added to x component + HitResult *hr = mc->level->clip(Vec3::newTemp(x + xo, y + yo, z + zo), Vec3::newTemp(x - xd + xo, y - yd + yo, z - zd + zo)); + if (hr != NULL) + { + double dist = hr->pos->distanceTo(Vec3::newTemp(x, y, z)); + if (dist < cameraDist) cameraDist = dist; + delete hr; + } + } + + // 4J - removed extra rotations here that aren't needed because our xRot/yRot don't ever + // deviate from the player's view direction +// glRotatef(player->xRot - xRot, 1, 0, 0); +// glRotatef(player->yRot - yRot, 0, 1, 0); + glTranslatef(0, 0, (float) -cameraDist); +// glRotatef(yRot - player->yRot, 0, 1, 0); +// glRotatef(xRot - player->xRot, 1, 0, 0); + } + } + else + { + glTranslatef(0, 0, -0.1f); + } + + if (!mc->options->fixedCamera) + { + glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, 1, 0, 0); + if( localplayer->ThirdPersonView() == 2 ) + { + // Third person view is now 0 for disabled, 1 for original, 2 for flipped + glRotatef(player->yRotO + (player->yRot - player->yRotO) * a, 0, 1, 0); + } + else + { + glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, 1, 0); + } + } + + glTranslatef(0, heightOffset, 0); + + x = player->xo + (player->x - player->xo) * a; + y = player->yo + (player->y - player->yo) * a - heightOffset; + z = player->zo + (player->z - player->zo) * a; + + isInClouds = mc->levelRenderer->isInCloud(x, y, z, a); + +} + + +void GameRenderer::zoomRegion(double zoom, double xa, double ya) +{ + this->zoom = zoom; + this->zoom_x = xa; + this->zoom_y = ya; +} + +void GameRenderer::unZoomRegion() +{ + zoom = 1; +} + +// 4J added as we have more complex adjustments to make for fov & aspect on account of viewports +void GameRenderer::getFovAndAspect(float& fov, float& aspect, float a, bool applyEffects) +{ + // 4J - split out aspect ratio and fov here so we can adjust for viewports - we might need to revisit these as + // they are maybe be too generous for performance. + aspect = mc->width / (float) mc->height; + fov = getFov(a, applyEffects); + + if( ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_TOP ) || + ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM ) ) + { + aspect *= 2.0f; + fov *= 0.7f; // Reduce FOV to make things less fish-eye, at the expense of reducing vertical FOV from single player mode + } + else if( ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_LEFT ) || + ( mc->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT) ) + { + // Ideally I'd like to make the fov bigger here, but if I do then you an see that the arm isn't very long... + aspect *= 0.5f; + } +} + +void GameRenderer::setupCamera(float a, int eye) +{ + renderDistance = (float)(16 * 16 >> (mc->options->viewDistance)); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + float stereoScale = 0.07f; + if (mc->options->anaglyph3d) glTranslatef(-(eye * 2 - 1) * stereoScale, 0, 0); + + // 4J - have split out fov & aspect calculation so we can take into account viewports + float aspect, fov; + getFovAndAspect(fov, aspect, a, true); + + if (zoom != 1) + { + glTranslatef((float) zoom_x, (float) -zoom_y, 0); + glScaled(zoom, zoom, 1); + } + gluPerspective(fov, aspect, 0.05f, renderDistance * 2); + + if (mc->gameMode->isCutScene()) + { + float s = 1 / 1.5f; + glScalef(1, s, 1); + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + if (mc->options->anaglyph3d) glTranslatef((eye * 2 - 1) * 0.10f, 0, 0); + + bobHurt(a); + + // 4J-PB - this is a per-player option + //if (mc->options->bobView) bobView(a); + + bool bNoLegAnim =(mc->player->getAnimOverrideBitmask()&(1<<HumanoidModel::eAnim_NoLegAnim))!=0; + bool bNoBobbingAnim =(mc->player->getAnimOverrideBitmask()&(1<<HumanoidModel::eAnim_NoBobbing))!=0; + + if(app.GetGameSettings(mc->player->GetXboxPad(),eGameSetting_ViewBob) && !mc->player->abilities.flying && !bNoLegAnim && !bNoBobbingAnim) bobView(a); + + float pt = mc->player->oPortalTime + (mc->player->portalTime - mc->player->oPortalTime) * a; + if (pt > 0) + { + int multiplier = 20; + if (mc->player->hasEffect(MobEffect::confusion)) + { + multiplier = 7; + } + + float skew = 5 / (pt * pt + 5) - pt * 0.04f; + skew *= skew; + glRotatef((_tick + a) * multiplier, 0, 1, 1); + glScalef(1 / skew, 1, 1); + glRotatef(-(_tick + a) * multiplier, 0, 1, 1); + } + + + moveCameraToPlayer(a); + + if (cameraFlip > 0) + { + int i = cameraFlip - 1; + if (i == 1) glRotatef(90, 0, 1, 0); + if (i == 2) glRotatef(180, 0, 1, 0); + if (i == 3) glRotatef(-90, 0, 1, 0); + if (i == 4) glRotatef(90, 1, 0, 0); + if (i == 5) glRotatef(-90, 1, 0, 0); + } +} + +void GameRenderer::renderItemInHand(float a, int eye) +{ + if (cameraFlip > 0) return; + + shared_ptr<LocalPlayer> localplayer = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer); + + // 4J-PB - to turn off the hand for screenshots, but not when the item held is a map + if ( localplayer!=NULL) + { + shared_ptr<ItemInstance> item = localplayer->inventory->getSelected(); + if(!(item && item->getItem()->id==Item::map_Id) && app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_DisplayHand)==0 ) return; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + + float stereoScale = 0.07f; + if (mc->options->anaglyph3d) glTranslatef(-(eye * 2 - 1) * stereoScale, 0, 0); + + // 4J - have split out fov & aspect calculation so we can take into account viewports + float fov, aspect; + getFovAndAspect(fov, aspect, a, false); + + if (zoom != 1) + { + glTranslatef((float) zoom_x, (float) -zoom_y, 0); + glScaled(zoom, zoom, 1); + } + gluPerspective(fov, aspect, 0.05f, renderDistance * 2); + + if (mc->gameMode->isCutScene()) + { + float s = 1 / 1.5f; + glScalef(1, s, 1); + } + + glMatrixMode(GL_MODELVIEW); + + + glLoadIdentity(); + if (mc->options->anaglyph3d) glTranslatef((eye * 2 - 1) * 0.10f, 0, 0); + + glPushMatrix(); + bobHurt(a); + + // 4J-PB - changing this to be per player + //if (mc->options->bobView) bobView(a); + bool bNoLegAnim =(localplayer->getAnimOverrideBitmask()&( (1<<HumanoidModel::eAnim_NoLegAnim) | (1<<HumanoidModel::eAnim_NoBobbing) ))!=0; + if(app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_ViewBob) && !localplayer->abilities.flying && !bNoLegAnim) bobView(a); + + // 4J-PB - changing this to be per player + //if (!mc->options->thirdPersonView && !mc->cameraTargetPlayer->isSleeping()) + if (!localplayer->ThirdPersonView() && !mc->cameraTargetPlayer->isSleeping()) + { + if (!mc->options->hideGui && !mc->gameMode->isCutScene()) + { + turnOnLightLayer(a); + PIXBeginNamedEvent(0,"Item in hand render"); + itemInHandRenderer->render(a); + PIXEndNamedEvent(); + turnOffLightLayer(a); + } + } + glPopMatrix(); + // 4J-PB - changing this to be per player + //if (!mc->options->thirdPersonView && !mc->cameraTargetPlayer->isSleeping()) + if (!localplayer->ThirdPersonView() && !mc->cameraTargetPlayer->isSleeping()) + { + itemInHandRenderer->renderScreenEffect(a); + bobHurt(a); + } + // 4J-PB - changing this to be per player + //if (mc->options->bobView) bobView(a); + if(app.GetGameSettings(localplayer->GetXboxPad(),eGameSetting_ViewBob) && !localplayer->abilities.flying && !bNoLegAnim) bobView(a); +} + +// 4J - change brought forward from 1.8.2 +void GameRenderer::turnOffLightLayer(double alpha) +{ // 4J - TODO +#if 0 + if (SharedConstants::TEXTURE_LIGHTING) + { + glClientActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + glClientActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); + } +#endif + RenderManager.TextureBindVertex(-1); +} + +// 4J - change brought forward from 1.8.2 +void GameRenderer::turnOnLightLayer(double alpha) +{ // 4J - TODO +#if 0 + if (SharedConstants::TEXTURE_LIGHTING) + { + glClientActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE1); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); +// float s = 1 / 16f / 15.0f*16/14.0f; + float s = 1 / 16.0f / 15.0f * 15 / 16; + glScalef(s, s, s); + glTranslatef(8f, 8f, 8f); + glMatrixMode(GL_MODELVIEW); + + mc->textures->bind(lightTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glColor4f(1, 1, 1, 1); + glEnable(GL_TEXTURE_2D); + glClientActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); + } +#endif + RenderManager.TextureBindVertex(getLightTexture(mc->player->GetXboxPad(), mc->level)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); +} + +// 4J - change brought forward from 1.8.2 +void GameRenderer::tickLightTexture() +{ + blrt += (float)((Math::random() - Math::random()) * Math::random() * Math::random()); + blgt += (float)((Math::random() - Math::random()) * Math::random() * Math::random()); + blrt *= 0.9; + blgt *= 0.9; + blr += (blrt - blr) * 1; + blg += (blgt - blg) * 1; + _updateLightTexture = true; +} + +void GameRenderer::updateLightTexture(float a) +{ + // 4J-JEV: Now doing light textures on PER PLAYER basis. + // 4J - we *had* added separate light textures for all dimensions, and this loop to update them all here + for(int j = 0; j < XUSER_MAX_COUNT; j++ ) + { + // Loop over all the players + shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[j]; + if (player == NULL) continue; + + Level *level = player->level; // 4J - was mc->level when it was just to update the one light texture + + float skyDarken1 = level->getSkyDarken((float) 1); + for (int i = 0; i < 256; i++) + { + float darken = skyDarken1 * 0.95f + 0.05f; + float sky = level->dimension->brightnessRamp[i / 16] * darken; + float block = level->dimension->brightnessRamp[i % 16] * (blr * 0.1f + 1.5f); + + if (level->lightningBoltTime > 0) + { + sky = level->dimension->brightnessRamp[i / 16]; + } + + float rs = sky * (skyDarken1 * 0.65f + 0.35f); + float gs = sky * (skyDarken1 * 0.65f + 0.35f); + float bs = sky; + + float rb = block; + float gb = block * ((block * 0.6f + 0.4f) * 0.6f + 0.4f); + float bb = block * ((block * block) * 0.6f + 0.4f); + + float _r = (rs + rb); + float _g = (gs + gb); + float _b = (bs + bb); + + _r = _r * 0.96f + 0.03f; + _g = _g * 0.96f + 0.03f; + _b = _b * 0.96f + 0.03f; + + if (level->dimension->id == 1) + { + _r = (0.22f + rb * 0.75f); + _g = (0.28f + gb * 0.75f); + _b = (0.25f + bb * 0.75f); + } + + if (player->hasEffect(MobEffect::nightVision)) + { + float scale = getNightVisionScale(player, a); + { + float dist = 1.0f / _r; + if (dist > (1.0f / _g)) + { + dist = (1.0f / _g); + } + if (dist > (1.0f / _b)) + { + dist = (1.0f / _b); + } + _r = _r * (1.0f - scale) + (_r * dist) * scale; + _g = _g * (1.0f - scale) + (_g * dist) * scale; + _b = _b * (1.0f - scale) + (_b * dist) * scale; + } + } + + float brightness = 0.0f; // 4J - TODO - was mc->options->gamma; + if (_r > 1) _r = 1; + if (_g > 1) _g = 1; + if (_b > 1) _b = 1; + + float ir = 1 - _r; + float ig = 1 - _g; + float ib = 1 - _b; + ir = 1 - (ir * ir * ir * ir); + ig = 1 - (ig * ig * ig * ig); + ib = 1 - (ib * ib * ib * ib); + _r = _r * (1 - brightness) + ir * brightness; + _g = _g * (1 - brightness) + ig * brightness; + _b = _b * (1 - brightness) + ib * brightness; + + + _r = _r * 0.96f + 0.03f; + _g = _g * 0.96f + 0.03f; + _b = _b * 0.96f + 0.03f; + + + if (_r > 1) _r = 1; + if (_g > 1) _g = 1; + if (_b > 1) _b = 1; + if (_r < 0) _r = 0; + if (_g < 0) _g = 0; + if (_b < 0) _b = 0; + + int a = 255; + int r = (int) (_r * 255); + int g = (int) (_g * 255); + int b = (int) (_b * 255); + +#if ( defined _DURANGO || defined _WIN64 || __PSVITA__ ) + lightPixels[j][i] = a << 24 | b << 16 | g << 8 | r; +#elif ( defined _XBOX || defined __ORBIS__ ) + lightPixels[j][i] = a << 24 | r << 16 | g << 8 | b; +#else + lightPixels[j][i] = r << 24 | g << 16 | b << 8 | a; +#endif + } + + mc->textures->replaceTextureDirect( lightPixels[j], 16, 16, getLightTexture(j,level) ); + } +} + +float GameRenderer::getNightVisionScale(shared_ptr<Player> player, float a) +{ + int duration = player->getEffect(MobEffect::nightVision)->getDuration(); + if (duration > (SharedConstants::TICKS_PER_SECOND * 10)) + { + return 1.0f; + } + else + { + float flash = max(0.0f, (float)duration - a); + return .7f + Mth::sin(flash * PI * .05f) * .3f; // was: .7 + sin(flash*pi*0.2) * .3 + } +} + +// 4J added, so we can have a light texture for each player to support split screen +int GameRenderer::getLightTexture(int iPad, Level *level) +{ + // Turn the current dimenions id into an index from 0 to 2 + // int idx = level->dimension->id; + // if( idx == -1 ) idx = 2; + + return lightTexture[iPad]; // 4J-JEV: Changing to Per Player lighting textures. +} + +void GameRenderer::render(float a, bool bFirst) +{ + if( _updateLightTexture && bFirst) updateLightTexture(a); + if (Display::isActive()) + { + lastActiveTime = System::currentTimeMillis(); + } + else + { + if (System::currentTimeMillis() - lastActiveTime > 500) + { + mc->pauseGame(); + } + } + +#if 0 // 4J - TODO + if (mc->mouseGrabbed) { + mc->mouseHandler.poll(); + + float ss = mc->options->sensitivity * 0.6f + 0.2f; + float sens = (ss * ss * ss) * 8; + float xo = mc->mouseHandler.xd * sens; + float yo = mc->mouseHandler.yd * sens; + + int yAxis = 1; + if (mc->options->invertYMouse) yAxis = -1; + + if (Minecraft.DEADMAU5_CAMERA_CHEATS) { + if (!mc->options->fixedCamera) { + if (Keyboard.isKeyDown(Keyboard.KEY_J)) { + xo = -12f * mc->options->sensitivity; + } else if (Keyboard.isKeyDown(Keyboard.KEY_L)) { + xo = 12f * mc->options->sensitivity; + } + if (Keyboard.isKeyDown(Keyboard.KEY_I)) { + yo = 12f * mc->options->sensitivity; + } else if (Keyboard.isKeyDown(Keyboard.KEY_K)) { + yo = -12f * mc->options->sensitivity; + } + } + } + + if (mc->options->smoothCamera) { + + xo = smoothTurnX.getNewDeltaValue(xo, .05f * sens); + yo = smoothTurnY.getNewDeltaValue(yo, .05f * sens); + + } + + mc->player.turn(xo, yo * yAxis); + } +#endif + + if (mc->noRender) return; + GameRenderer::anaglyph3d = mc->options->anaglyph3d; + + glViewport(0, 0, mc->width, mc->height); // 4J - added + ScreenSizeCalculator ssc(mc->options, mc->width, mc->height); + int screenWidth = ssc.getWidth(); + int screenHeight = ssc.getHeight(); + int xMouse = Mouse::getX() * screenWidth / mc->width; + int yMouse = screenHeight - Mouse::getY() * screenHeight / mc->height - 1; + + int maxFps = getFpsCap(mc->options->framerateLimit); + + if (mc->level != NULL) + { + if (mc->options->framerateLimit == 0) + { + renderLevel(a, 0); + } + else + { + renderLevel(a, lastNsTime + 1000000000 / maxFps); + } + + lastNsTime = System::nanoTime(); + + + if (!mc->options->hideGui || mc->screen != NULL) + { + mc->gui->render(a, mc->screen != NULL, xMouse, yMouse); + } + } + else + { + glViewport(0, 0, mc->width, mc->height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + setupGuiScreen(); + + lastNsTime = System::nanoTime(); + } + + + if (mc->screen != NULL) + { + glClear(GL_DEPTH_BUFFER_BIT); + mc->screen->render(xMouse, yMouse, a); + if (mc->screen != NULL && mc->screen->particles != NULL) mc->screen->particles->render(a); + } + +} + +void GameRenderer::renderLevel(float a) +{ + renderLevel(a, 0); +} + +#ifdef MULTITHREAD_ENABLE +// Request that an item be deleted, when it is safe to do so +void GameRenderer::AddForDelete(byte *deleteThis) +{ + EnterCriticalSection(&m_csDeleteStack); + m_deleteStackByte.push_back(deleteThis); +} + +void GameRenderer::AddForDelete(SparseLightStorage *deleteThis) +{ + EnterCriticalSection(&m_csDeleteStack); + m_deleteStackSparseLightStorage.push_back(deleteThis); +} + +void GameRenderer::AddForDelete(CompressedTileStorage *deleteThis) +{ + EnterCriticalSection(&m_csDeleteStack); + m_deleteStackCompressedTileStorage.push_back(deleteThis); +} + +void GameRenderer::AddForDelete(SparseDataStorage *deleteThis) +{ + EnterCriticalSection(&m_csDeleteStack); + m_deleteStackSparseDataStorage.push_back(deleteThis); +} + +void GameRenderer::FinishedReassigning() +{ + LeaveCriticalSection(&m_csDeleteStack); +} + +int GameRenderer::runUpdate(LPVOID lpParam) +{ + Minecraft *minecraft = Minecraft::GetInstance(); + Vec3::CreateNewThreadStorage(); + AABB::CreateNewThreadStorage(); + IntCache::CreateNewThreadStorage(); + Tesselator::CreateNewThreadStorage(1024*1024); + Compression::UseDefaultThreadStorage(); + RenderManager.InitialiseContext(); +#ifdef _LARGE_WORLDS + Chunk::CreateNewThreadStorage(); +#endif + Tile::CreateNewThreadStorage(); + + ShutdownManager::HasStarted(ShutdownManager::eRenderChunkUpdateThread,m_updateEvents); + while(ShutdownManager::ShouldRun(ShutdownManager::eRenderChunkUpdateThread)) + { + //m_updateEvents->Clear(eUpdateEventIsFinished); + //m_updateEvents->WaitForSingle(eUpdateCanRun,INFINITE); + // 4J Stu - We Need to have this happen atomically to avoid deadlocks + m_updateEvents->WaitForAll(INFINITE); + + if( !ShutdownManager::ShouldRun(ShutdownManager::eRenderChunkUpdateThread) ) + { + break; + } + + m_updateEvents->Set(eUpdateCanRun); + +// PIXBeginNamedEvent(0,"Updating dirty chunks %d",(count++)&7); + + // Update chunks atomically until there aren't any very near ones left - they will be deferred for rendering + // until the call to CBuffDeferredModeEnd if we have anything near to render here + // Now limiting maximum number of updates that can be deferred as have noticed that with redstone clock circuits, it is possible to create + // things that need constant updating, so if you stand near them, the render data Never gets updated and the game just keeps going until it runs out of render memory... + int count = 0; + static const int MAX_DEFERRED_UPDATES = 10; + bool shouldContinue = false; + do + { + shouldContinue = minecraft->levelRenderer->updateDirtyChunks(); + count++; + } while ( shouldContinue && count < MAX_DEFERRED_UPDATES ); + +// while( minecraft->levelRenderer->updateDirtyChunks() ) +// ; + RenderManager.CBuffDeferredModeEnd(); + + // If any renderable tile entities were flagged in this last block of chunk(s) that were udpated, then change their + // flags to say that this deferred chunk is over and they are actually safe to be removed now + minecraft->levelRenderer->fullyFlagRenderableTileEntitiesToBeRemoved(); + + // We've got stacks for things that can only safely be deleted whilst this thread isn't updating things - delete those things now + EnterCriticalSection(&m_csDeleteStack); + for(unsigned int i = 0; i < m_deleteStackByte.size(); i++ ) + { + delete m_deleteStackByte[i]; + } + m_deleteStackByte.clear(); + for(unsigned int i = 0; i < m_deleteStackSparseLightStorage.size(); i++ ) + { + delete m_deleteStackSparseLightStorage[i]; + } + m_deleteStackSparseLightStorage.clear(); + for(unsigned int i = 0; i < m_deleteStackCompressedTileStorage.size(); i++ ) + { + delete m_deleteStackCompressedTileStorage[i]; + } + m_deleteStackCompressedTileStorage.clear(); + for(unsigned int i = 0; i < m_deleteStackSparseDataStorage.size(); i++ ) + { + delete m_deleteStackSparseDataStorage[i]; + } + m_deleteStackSparseDataStorage.clear(); + LeaveCriticalSection(&m_csDeleteStack); + +// PIXEndNamedEvent(); + + AABB::resetPool(); + Vec3::resetPool(); + IntCache::Reset(); + m_updateEvents->Set(eUpdateEventIsFinished); + } + + ShutdownManager::HasFinished(ShutdownManager::eRenderChunkUpdateThread); + return 0; +} +#endif + +void GameRenderer::EnableUpdateThread() +{ +// #ifdef __PS3__ // MGH - disable the update on PS3 for now +// return; +// #endif +#ifdef MULTITHREAD_ENABLE + if( updateRunning) return; + app.DebugPrintf("------------------EnableUpdateThread--------------------\n"); + updateRunning = true; + m_updateEvents->Set(eUpdateCanRun); + m_updateEvents->Set(eUpdateEventIsFinished); +#endif +} + +void GameRenderer::DisableUpdateThread() +{ +// #ifdef __PS3__ // MGH - disable the update on PS3 for now +// return; +// #endif +#ifdef MULTITHREAD_ENABLE + if( !updateRunning) return; + app.DebugPrintf("------------------DisableUpdateThread--------------------\n"); + updateRunning = false; + m_updateEvents->Clear(eUpdateCanRun); + m_updateEvents->WaitForSingle(eUpdateEventIsFinished,INFINITE); +#endif +} + +void GameRenderer::renderLevel(float a, __int64 until) +{ +// if (updateLightTexture) updateLightTexture(); // 4J - TODO - Java 1.0.1 has this line enabled, should check why - don't want to put it in now in case it breaks split-screen + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + // Is this the primary player? Only do the updating of chunks if it is. This controls the creation of render data for each chunk - all of this we are only + // going to do for the primary player, and the other players can just view whatever they have loaded in - we're sharing render data between players. + bool updateChunks = ( mc->player == mc->localplayers[ProfileManager.GetPrimaryPad()] ); + +// if (mc->cameraTargetPlayer == NULL) // 4J - removed condition as we want to update this is mc->player changes for different local players + { + mc->cameraTargetPlayer = mc->player; + } + pick(a); + + shared_ptr<Mob> cameraEntity = mc->cameraTargetPlayer; + LevelRenderer *levelRenderer = mc->levelRenderer; + ParticleEngine *particleEngine = mc->particleEngine; + double xOff = cameraEntity->xOld + (cameraEntity->x - cameraEntity->xOld) * a; + double yOff = cameraEntity->yOld + (cameraEntity->y - cameraEntity->yOld) * a; + double zOff = cameraEntity->zOld + (cameraEntity->z - cameraEntity->zOld) * a; + + for (int i = 0; i < 2; i++) + { + if (mc->options->anaglyph3d) + { + GameRenderer::anaglyphPass = i; + if (GameRenderer::anaglyphPass == 0) glColorMask(false, true, true, false); + else glColorMask(true, false, false, false); + } + + + glViewport(0, 0, mc->width, mc->height); + setupClearColor(a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_CULL_FACE); + + setupCamera(a, i); + Camera::prepare(mc->player, mc->player->ThirdPersonView() == 2); + + Frustum::getFrustum(); + if (mc->options->viewDistance < 2) + { + setupFog(-1, a); + levelRenderer->renderSky(a); + if(mc->skins->getSelected()->getId() == 1026 ) levelRenderer->renderHaloRing(a); + } + glEnable(GL_FOG); + setupFog(1, a); + + if (mc->options->ambientOcclusion) + { + GL11::glShadeModel(GL11::GL_SMOOTH); + } + + PIXBeginNamedEvent(0,"Culling"); + MemSect(31); +// Culler *frustum = new FrustumCuller(); + FrustumCuller frustObj; + Culler *frustum = &frustObj; + MemSect(0); + frustum->prepare(xOff, yOff, zOff); + + mc->levelRenderer->cull(frustum, a); + PIXEndNamedEvent(); + +#ifndef MULTITHREAD_ENABLE + if ( (i == 0) && updateChunks ) // 4J - added updateChunks condition + { + int PIXPass = 0; + PIXBeginNamedEvent(0,"Updating dirty chunks"); + do + { + PIXBeginNamedEvent(0,"Updating dirty chunks pass %d",PIXPass++); + bool retval = mc->levelRenderer->updateDirtyChunks(cameraEntity, false); + PIXEndNamedEvent(); + if( retval ) break; + + + if (until == 0) break; + + __int64 diff = until - System::nanoTime(); + if (diff < 0) break; + if (diff > 1000000000) break; + } while (true); + PIXEndNamedEvent(); + } +#endif + setupFog(0, a); + glEnable(GL_FOG); + MemSect(31); + mc->textures->bindTexture(TN_TERRAIN); // 4J was L"/terrain.png" + MemSect(0); + Lighting::turnOff(); + PIXBeginNamedEvent(0,"Level render"); + levelRenderer->render(cameraEntity, 0, a, updateChunks); + PIXEndNamedEvent(); + + GL11::glShadeModel(GL11::GL_FLAT); + + if (cameraFlip == 0 ) + { + Lighting::turnOn(); + PIXBeginNamedEvent(0,"Entity render"); + // 4J - for entities, don't include the "a" factor that interpolates from the old to new position, as the AABBs for the entities are already fully at the new position + // This fixes flickering minecarts, and pigs that you are riding on + frustum->prepare(cameraEntity->x,cameraEntity->y,cameraEntity->z); + // 4J Stu - When rendering entities, in the end if the dragon is hurt or we have a lot of entities we can end up wrapping + // our index into the temp Vec3 cache and overwrite the one that was storing the camera position + // Fix for #77745 - TU9: Content: Gameplay: Items and mobs not belonging to end world are disappearing when Enderdragon is damaged. + Vec3 *cameraPosTemp = cameraEntity->getPos(a); + cameraPos->x = cameraPosTemp->x; + cameraPos->y = cameraPosTemp->y; + cameraPos->z = cameraPosTemp->z; + levelRenderer->renderEntities(cameraPos, frustum, a); +#ifdef __PSVITA__ + // AP - make sure we're using the Alpha cut out effect for particles + glEnable(GL_ALPHA_TEST); +#endif + PIXEndNamedEvent(); + PIXBeginNamedEvent(0,"Particle render"); + turnOnLightLayer(a); // 4J - brought forward from 1.8.2 + particleEngine->renderLit(cameraEntity, a); + Lighting::turnOff(); + setupFog(0, a); + particleEngine->render(cameraEntity, a); + PIXEndNamedEvent(); + turnOffLightLayer(a); // 4J - brought forward from 1.8.2 + + shared_ptr<Player> player = dynamic_pointer_cast<Player>(cameraEntity); + if (mc->hitResult != NULL && cameraEntity->isUnderLiquid(Material::water) && player!=NULL) //&& !mc->options.hideGui) + { + //shared_ptr<Player> player = dynamic_pointer_cast<Player>(cameraEntity); + glDisable(GL_ALPHA_TEST); + levelRenderer->renderHit(player, mc->hitResult, 0, player->inventory->getSelected(), a); + levelRenderer->renderHitOutline(player, mc->hitResult, 0, player->inventory->getSelected(), a); + glEnable(GL_ALPHA_TEST); + } + } + + glDisable(GL_BLEND); + glEnable(GL_CULL_FACE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(true); + setupFog(0, a); + glEnable(GL_BLEND); + glDisable(GL_CULL_FACE); + MemSect(31); + mc->textures->bindTexture(TN_TERRAIN); // 4J was L"/terrain.png" + MemSect(0); + // 4J - have changed this fancy rendering option to work with our command buffers. The original used to use frame buffer flags to disable + // writing to colour when doing the z-only pass, but that value gets obliterated by our command buffers. Using alpha blend function instead + // to achieve the same effect. + if (true) // (mc->options->fancyGraphics) + { + if (mc->options->ambientOcclusion) + { + GL11::glShadeModel(GL11::GL_SMOOTH); + } + + glBlendFunc(GL_ZERO, GL_ONE); + PIXBeginNamedEvent(0,"Fancy second pass - writing z"); + int visibleWaterChunks = levelRenderer->render(cameraEntity, 1, a, updateChunks); + PIXEndNamedEvent(); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (visibleWaterChunks > 0) + { + PIXBeginNamedEvent(0,"Fancy second pass - actual rendering"); + levelRenderer->render(cameraEntity, 1, a, updateChunks); // 4J - chanaged, used to be renderSameAsLast but we don't support that anymore + PIXEndNamedEvent(); + } + + GL11::glShadeModel(GL11::GL_FLAT); + } + else + { + PIXBeginNamedEvent(0,"Second pass level render"); + levelRenderer->render(cameraEntity, 1, a, updateChunks); + PIXEndNamedEvent(); + } + + + glDepthMask(true); + glEnable(GL_CULL_FACE); + glDisable(GL_BLEND); + + if (zoom == 1 && (dynamic_pointer_cast<Player>(cameraEntity)!=NULL)) //&& !mc->options.hideGui) + { + if (mc->hitResult != NULL && !cameraEntity->isUnderLiquid(Material::water)) + { + shared_ptr<Player> player = dynamic_pointer_cast<Player>(cameraEntity); + glDisable(GL_ALPHA_TEST); + levelRenderer->renderHit(player, mc->hitResult, 0, player->inventory->getSelected(), a); + levelRenderer->renderHitOutline(player, mc->hitResult, 0, player->inventory->getSelected(), a); + glEnable(GL_ALPHA_TEST); + } + } + + /* 4J - moved rain rendering to after clouds so that it alpha blends onto them properly + PIXBeginNamedEvent(0,"Rendering snow and rain"); + renderSnowAndRain(a); + PIXEndNamedEvent(); + glDisable(GL_FOG); + */ + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + levelRenderer->renderDestroyAnimation(Tesselator::getInstance(), dynamic_pointer_cast<Player>(cameraEntity), a); + glDisable(GL_BLEND); + + if (mc->options->isCloudsOn()) + { + glPushMatrix(); + setupFog(0, a); + glEnable(GL_FOG); + PIXBeginNamedEvent(0,"Rendering clouds"); + levelRenderer->renderClouds(a); + PIXEndNamedEvent(); + glDisable(GL_FOG); + setupFog(1, a); + glPopMatrix(); + } + + // 4J - rain rendering moved here so that it renders after clouds & can blend properly onto them + setupFog(0, a); + glEnable(GL_FOG); + PIXBeginNamedEvent(0,"Rendering snow and rain"); + renderSnowAndRain(a); + PIXEndNamedEvent(); + glDisable(GL_FOG); + + + if (zoom == 1) + { + glClear(GL_DEPTH_BUFFER_BIT); + renderItemInHand(a, i); + } + + + if (!mc->options->anaglyph3d) + { + return; + } + } + glColorMask(true, true, true, false); +} + +void GameRenderer::tickRain() +{ + float rainLevel = mc->level->getRainLevel(1); + + if (!mc->options->fancyGraphics) rainLevel /= 2; + if (rainLevel == 0) return; + + rainLevel /= ( mc->levelRenderer->activePlayers() + 1 ); + + random->setSeed(_tick * 312987231l); + shared_ptr<Mob> player = mc->cameraTargetPlayer; + Level *level = mc->level; + + int x0 = Mth::floor(player->x); + int y0 = Mth::floor(player->y); + int z0 = Mth::floor(player->z); + + int r = 10; + + double rainPosX = 0; + double rainPosY = 0; + double rainPosZ = 0; + int rainPosSamples = 0; + + int rainCount = (int) (100 * rainLevel * rainLevel); + if (mc->options->particles == 1) + { + rainCount >>= 1; + } else if (mc->options->particles == 2) + { + rainCount = 0; + } + for (int i = 0; i < rainCount; i++) + { + int x = x0 + random->nextInt(r) - random->nextInt(r); + int z = z0 + random->nextInt(r) - random->nextInt(r); + int y = level->getTopRainBlock(x, z); + int t = level->getTile(x, y - 1, z); + Biome *biome = level->getBiome(x,z); + if (y <= y0 + r && y >= y0 - r && biome->hasRain() && biome->getTemperature() >= 0.2f) + { + float xa = random->nextFloat(); + float za = random->nextFloat(); + if (t > 0) + { + if (Tile::tiles[t]->material == Material::lava) + { + mc->particleEngine->add( shared_ptr<SmokeParticle>( new SmokeParticle(level, x + xa, y + 0.1f - Tile::tiles[t]->getShapeY0(), z + za, 0, 0, 0) ) ); + } + else + { + if (random->nextInt(++rainPosSamples) == 0) + { + rainPosX = x + xa; + rainPosY = y + 0.1f - Tile::tiles[t]->getShapeY0(); + rainPosZ = z + za; + } + mc->particleEngine->add( shared_ptr<WaterDropParticle>( new WaterDropParticle(level, x + xa, y + 0.1f - Tile::tiles[t]->getShapeY0(), z + za) ) ); + } + } + } + } + + + if (rainPosSamples > 0 && random->nextInt(3) < rainSoundTime++) + { + rainSoundTime = 0; + MemSect(24); + if (rainPosY > player->y + 1 && level->getTopRainBlock(Mth::floor(player->x), Mth::floor(player->z)) > Mth::floor(player->y)) + { + mc->level->playLocalSound(rainPosX, rainPosY, rainPosZ, eSoundType_AMBIENT_WEATHER_RAIN, 0.1f, 0.5f); + } + else + { + mc->level->playLocalSound(rainPosX, rainPosY, rainPosZ, eSoundType_AMBIENT_WEATHER_RAIN, 0.2f, 1.0f); + } + MemSect(0); + } + +} + +// 4J - this whole function updated from 1.8.2 +void GameRenderer::renderSnowAndRain(float a) +{ + float rainLevel = mc->level->getRainLevel(a); + if (rainLevel <= 0) return; + + // 4J - rain is relatively low poly, but high fill-rate - better to clip it + RenderManager.StateSetEnableViewportClipPlanes(true); + + this->turnOnLightLayer(a); + + if (rainXa == NULL) + { + rainXa = new float[32 * 32]; + rainZa = new float[32 * 32]; + + for (int z = 0; z < 32; z++) + { + for (int x = 0; x < 32; x++) + { + float xa = x - 16; + float za = z - 16; + float d = Mth::sqrt(xa * xa + za * za); + rainXa[z << 5 | x] = -za / d; + rainZa[z << 5 | x] = xa / d; + } + } + } + + shared_ptr<Mob> player = mc->cameraTargetPlayer; + Level *level = mc->level; + + int x0 = Mth::floor(player->x); + int y0 = Mth::floor(player->y); + int z0 = Mth::floor(player->z); + + Tesselator *t = Tesselator::getInstance(); + glDisable(GL_CULL_FACE); + glNormal3f(0, 1, 0); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glAlphaFunc(GL_GREATER, 0.01f); + + MemSect(31); + mc->textures->bindTexture(TN_ENVIRONMENT_SNOW); // 4J was L"/environment/snow.png" + MemSect(0); + + double xo = player->xOld + (player->x - player->xOld) * a; + double yo = player->yOld + (player->y - player->yOld) * a; + double zo = player->zOld + (player->z - player->zOld) * a; + + int yMin = Mth::floor(yo); + + + int r = 5; + // 4J - was if(mc.options.fancyGraphics) r = 10; + switch( mc->levelRenderer->activePlayers() ) + { + case 1: + default: + r = 9; + break; + case 2: + r = 7; + break; + case 3: + r = 5; + break; + case 4: + r = 5; + break; + } + + // 4J - some changes made here to access biome through new interface that caches results in levelchunk flags, as an optimisation + + int mode = -1; + float time = _tick + a; + + glColor4f(1, 1, 1, 1); + + for (int x = x0 - r; x <= x0 + r; x++) + for (int z = z0 - r; z <= z0 + r; z++) + { + int rainSlot = (z - z0 + 16) * 32 + (x - x0 + 16); + float xa = rainXa[rainSlot] * 0.5f; + float za = rainZa[rainSlot] * 0.5f; + + // 4J - changes here brought forward from 1.8.2 + Biome *b = level->getBiome(x, z); + if (!b->hasRain() && !b->hasSnow()) continue; + + int floor = level->getTopRainBlock(x, z); + + int yy0 = y0 - r; + int yy1 = y0 + r; + + if (yy0 < floor) yy0 = floor; + if (yy1 < floor) yy1 = floor; + float s = 1; + + int yl = floor; + if (yl < yMin) yl = yMin; + + if (yy0 != yy1) + { + random->setSeed((x * x * 3121 + x * 45238971) ^ (z * z * 418711 + z * 13761)); + + // 4J - changes here brought forward from 1.8.2 + float temp = b->getTemperature(); + if (level->getBiomeSource()->scaleTemp(temp, floor) >= 0.15f) + { + if (mode != 0) + { + if (mode >= 0) t->end(); + mode = 0; + mc->textures->bindTexture(TN_ENVIRONMENT_RAIN); + t->begin(); + } + + float ra = (((_tick + x * x * 3121 + x * 45238971 + z * z * 418711 + z * 13761) & 31) + a) / 32.0f * (3 + random->nextFloat()); + + double xd = (x + 0.5f) - player->x; + double zd = (z + 0.5f) - player->z; + float dd = (float) Mth::sqrt(xd * xd + zd * zd) / r; + + float br = 1; + t->offset(-xo * 1, -yo * 1, -zo * 1); +#ifdef __PSVITA__ + // AP - this will set up the 4 vertices in half the time + float Alpha = ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel; + int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4; + t->tileRainQuad(x - xa + 0.5, yy0, z - za + 0.5, 0 * s, yy0 * s / 4.0f + ra * s, + x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s, + x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s, + x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s, + br, br, br, Alpha, br, br, br, 0, tex2); +#else + t->tex2(level->getLightColor(x, yl, z, 0)); + t->color(br, br, br, ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel); + t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s, yy0 * s / 4.0f + ra * s); + t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s); + t->color(br, br, br, 0.0f); // 4J - added to soften the top visible edge of the rain + t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s); + t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s); +#endif + t->offset(0, 0, 0); + t->end(); + } + else + { + if (mode != 1) + { + if (mode >= 0) t->end(); + mode = 1; + mc->textures->bindTexture(TN_ENVIRONMENT_SNOW); + t->begin(); + } + float ra = (((_tick) & 511) + a) / 512.0f; + float uo = random->nextFloat() + time * 0.01f * (float) random->nextGaussian(); + float vo = random->nextFloat() + time * (float) random->nextGaussian() * 0.001f; + double xd = (x + 0.5f) - player->x; + double zd = (z + 0.5f) - player->z; + float dd = (float) sqrt(xd * xd + zd * zd) / r; + float br = 1; + t->offset(-xo * 1, -yo * 1, -zo * 1); +#ifdef __PSVITA__ + // AP - this will set up the 4 vertices in half the time + float Alpha = ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel; + int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4; + t->tileRainQuad(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo, yy0 * s / 4.0f + ra * s + vo, + x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo, + x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo, + x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo, + br, br, br, Alpha, br, br, br, Alpha, tex2); +#else + t->tex2((level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4); + t->color(br, br, br, ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel); + t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo, yy0 * s / 4.0f + ra * s + vo); + t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo); + t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo); + t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo); +#endif + t->offset(0, 0, 0); + } + } + } + + if( mode >= 0 ) t->end(); + glEnable(GL_CULL_FACE); + glDisable(GL_BLEND); + glAlphaFunc(GL_GREATER, 0.1f); + this->turnOffLightLayer(a); + + RenderManager.StateSetEnableViewportClipPlanes(false); +} + +// 4J - added forceScale parameter +void GameRenderer::setupGuiScreen(int forceScale /*=-1*/) +{ + ScreenSizeCalculator ssc(mc->options, mc->width, mc->height, forceScale); + + glClear(GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, (float)ssc.rawWidth, (float)ssc.rawHeight, 0, 1000, 3000); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -2000); +} + +void GameRenderer::setupClearColor(float a) +{ + Level *level = mc->level; + shared_ptr<Mob> player = mc->cameraTargetPlayer; + + float whiteness = 1.0f / (4 - mc->options->viewDistance); + whiteness = 1 - (float) pow((double)whiteness, 0.25); + + Vec3 *skyColor = level->getSkyColor(mc->cameraTargetPlayer, a); + float sr = (float) skyColor->x; + float sg = (float) skyColor->y; + float sb = (float) skyColor->z; + + Vec3 *fogColor = level->getFogColor(a); + fr = (float) fogColor->x; + fg = (float) fogColor->y; + fb = (float) fogColor->z; + + if (mc->options->viewDistance < 2) + { + Vec3 *sunAngle = Mth::sin(level->getSunAngle(a)) > 0 ? Vec3::newTemp(-1, 0, 0) : Vec3::newTemp(1, 0, 0); + float d = (float) player->getViewVector(a)->dot(sunAngle); + if (d < 0) d = 0; + if (d > 0) + { + float *c = level->dimension->getSunriseColor(level->getTimeOfDay(a), a); + if (c != NULL) + { + d *= c[3]; + fr = fr * (1 - d) + c[0] * d; + fg = fg * (1 - d) + c[1] * d; + fb = fb * (1 - d) + c[2] * d; + } + } + } + + fr += (sr - fr) * whiteness; + fg += (sg - fg) * whiteness; + fb += (sb - fb) * whiteness; + + float rainLevel = level->getRainLevel(a); + if (rainLevel > 0) + { + float ba = 1 - rainLevel * 0.5f; + float bb = 1 - rainLevel * 0.4f; + fr *= ba; + fg *= ba; + fb *= bb; + } + float thunderLevel = level->getThunderLevel(a); + if (thunderLevel > 0) + { + float ba = 1 - thunderLevel * 0.5f; + fr *= ba; + fg *= ba; + fb *= ba; + } + + int t = Camera::getBlockAt(mc->level, player, a); + if (isInClouds) + { + Vec3 *cc = level->getCloudColor(a); + fr = (float) cc->x; + fg = (float) cc->y; + fb = (float) cc->z; + } + else if (t != 0 && Tile::tiles[t]->material == Material::water) + { + + unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Water_Clear_Colour ); + byte redComponent = ((colour>>16)&0xFF); + byte greenComponent = ((colour>>8)&0xFF); + byte blueComponent = ((colour)&0xFF); + + fr = (float)redComponent/256;//0.02f; + fg = (float)greenComponent/256;//0.02f; + fb = (float)blueComponent/256;//0.2f; + } + else if (t != 0 && Tile::tiles[t]->material == Material::lava) + { + + unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Lava_Clear_Colour ); + byte redComponent = ((colour>>16)&0xFF); + byte greenComponent = ((colour>>8)&0xFF); + byte blueComponent = ((colour)&0xFF); + + fr = (float)redComponent/256;//0.6f; + fg = (float)greenComponent/256;//0.1f; + fb = (float)blueComponent/256;//0.00f; + } + + float brr = fogBrO + (fogBr - fogBrO) * a; + fr *= brr; + fg *= brr; + fb *= brr; + + double yy = (player->yOld + (player->y - player->yOld) * a) * level->dimension->getClearColorScale(); // 4J - getClearColorScale brought forward from 1.2.3 + + if (player->hasEffect(MobEffect::blindness)) + { + int duration = player->getEffect(MobEffect::blindness)->getDuration(); + if (duration < 20) + { + yy = yy * (1.0f - (float) duration / 20.0f); + } + else + { + yy = 0; + } + } + + if (yy < 1) + { + if (yy < 0) yy = 0; + yy = yy * yy; + fr *= yy; + fg *= yy; + fb *= yy; + } + + if (player->hasEffect(MobEffect::nightVision)) + { + float scale = getNightVisionScale(mc->player, a); + { + float dist = FLT_MAX; // MGH - changed this to avoid divide by zero + if ( (fr > 0) && (dist > (1.0f / fr)) ) + { + dist = (1.0f / fr); + } + if ( (fg > 0) && (dist > (1.0f / fg)) ) + { + dist = (1.0f / fg); + } + if ( (fb > 0) && (dist > (1.0f / fb)) ) + { + dist = (1.0f / fb); + } + fr = fr * (1.0f - scale) + (fr * dist) * scale; + fg = fg * (1.0f - scale) + (fg * dist) * scale; + fb = fb * (1.0f - scale) + (fb * dist) * scale; + } + } + + if (mc->options->anaglyph3d) + { + float frr = (fr * 30 + fg * 59 + fb * 11) / 100; + float fgg = (fr * 30 + fg * 70) / (100); + float fbb = (fr * 30 + fb * 70) / (100); + + fr = frr; + fg = fgg; + fb = fbb; + } + + glClearColor(fr, fg, fb, 0.0f); + +} + +void GameRenderer::setupFog(int i, float alpha) +{ + shared_ptr<Mob> player = mc->cameraTargetPlayer; + + // 4J - check for creative mode brought forward from 1.2.3 + bool creative = false; + if (dynamic_pointer_cast<Player>(player) ) + { + creative = (dynamic_pointer_cast<Player>(player))->abilities.instabuild; + } + + if (i == 999) + { + __debugbreak(); + // 4J TODO + /* + glFog(GL_FOG_COLOR, getBuffer(0, 0, 0, 1)); + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogf(GL_FOG_START, 0); + glFogf(GL_FOG_END, 8); + + if (GLContext.getCapabilities().GL_NV_fog_distance) { + glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV); + } + + glFogf(GL_FOG_START, 0); + */ + return; + } + + glFog(GL_FOG_COLOR, getBuffer(fr, fg, fb, 1)); + glNormal3f(0, -1, 0); + glColor4f(1, 1, 1, 1); + + int t = Camera::getBlockAt(mc->level, player, alpha); + + if (player->hasEffect(MobEffect::blindness)) + { + float distance = 5.0f; + int duration = player->getEffect(MobEffect::blindness)->getDuration(); + if (duration < 20) + { + distance = 5.0f + (renderDistance - 5.0f) * (1.0f - (float) duration / 20.0f); + } + + glFogi(GL_FOG_MODE, GL_LINEAR); + if (i < 0) + { + glFogf(GL_FOG_START, 0); + glFogf(GL_FOG_END, distance * 0.8f); + } + else + { + glFogf(GL_FOG_START, distance * 0.25f); + glFogf(GL_FOG_END, distance); + } + // 4J - TODO investigate implementing this +// if (GLContext.getCapabilities().GL_NV_fog_distance) +// { +// glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV); +// } + } + else if (isInClouds) + { + glFogi(GL_FOG_MODE, GL_EXP); + glFogf(GL_FOG_DENSITY, 0.1f); // was 0.06 + + unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_In_Cloud_Fog_Colour ); + byte redComponent = ((colour>>16)&0xFF); + byte greenComponent = ((colour>>8)&0xFF); + byte blueComponent = ((colour)&0xFF); + + float rr = (float)redComponent/256;//1.0f; + float gg = (float)greenComponent/256;//1.0f; + float bb = (float)blueComponent/256;//1.0f; + + if (mc->options->anaglyph3d) + { + float rrr = (rr * 30 + gg * 59 + bb * 11) / 100; + float ggg = (rr * 30 + gg * 70) / (100); + float bbb = (rr * 30 + bb * 70) / (100); + + rr = rrr; + gg = ggg; + bb = bbb; + } + } + else if (t > 0 && Tile::tiles[t]->material == Material::water) + { + glFogi(GL_FOG_MODE, GL_EXP); + if (player->hasEffect(MobEffect::waterBreathing)) + { + glFogf(GL_FOG_DENSITY, 0.05f); // was 0.06 + } + else + { + glFogf(GL_FOG_DENSITY, 0.1f); // was 0.06 + } + + unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Water_Fog_Colour ); + byte redComponent = ((colour>>16)&0xFF); + byte greenComponent = ((colour>>8)&0xFF); + byte blueComponent = ((colour)&0xFF); + + float rr = (float)redComponent/256;//0.4f; + float gg = (float)greenComponent/256;//0.4f; + float bb = (float)blueComponent/256;//0.9f; + + if (mc->options->anaglyph3d) + { + float rrr = (rr * 30 + gg * 59 + bb * 11) / 100; + float ggg = (rr * 30 + gg * 70) / (100); + float bbb = (rr * 30 + bb * 70) / (100); + + rr = rrr; + gg = ggg; + bb = bbb; + } + } + else if (t > 0 && Tile::tiles[t]->material == Material::lava) + { + glFogi(GL_FOG_MODE, GL_EXP); + glFogf(GL_FOG_DENSITY, 2.0f); // was 0.06 + + unsigned int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Under_Lava_Fog_Colour ); + byte redComponent = ((colour>>16)&0xFF); + byte greenComponent = ((colour>>8)&0xFF); + byte blueComponent = ((colour)&0xFF); + + float rr = (float)redComponent/256;//0.4f; + float gg = (float)greenComponent/256;//0.3f; + float bb = (float)blueComponent/256;//0.3f; + + if (mc->options->anaglyph3d) + { + float rrr = (rr * 30 + gg * 59 + bb * 11) / 100; + float ggg = (rr * 30 + gg * 70) / (100); + float bbb = (rr * 30 + bb * 70) / (100); + + rr = rrr; + gg = ggg; + bb = bbb; + } + } + else + { + float distance = renderDistance; + if (!mc->level->dimension->hasCeiling) + { + // 4J - test for doing bedrockfog brought forward from 1.2.3 + if (mc->level->dimension->hasBedrockFog() && !creative) + { + double yy = ((player->getLightColor(alpha) & 0xf00000) >> 20) / 16.0 + (player->yOld + (player->y - player->yOld) * alpha + 4) / 32; + if (yy < 1) + { + if (yy < 0) yy = 0; + yy = yy * yy; + float dist = 100 * (float) yy; + if (dist < 5) dist = 5; + if (distance > dist) distance = dist; + } + } + } + + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogf(GL_FOG_START, distance * 0.25f); + glFogf(GL_FOG_END, distance); + if (i < 0) + { + glFogf(GL_FOG_START, 0); + glFogf(GL_FOG_END, distance * 0.8f); + } + else + { + glFogf(GL_FOG_START, distance * 0.25f); + glFogf(GL_FOG_END, distance); + } + /* 4J - removed - TODO investigate + if (GLContext.getCapabilities().GL_NV_fog_distance) + { + glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV); + } + */ + + if (mc->level->dimension->isFoggyAt((int) player->x, (int) player->z)) + { + glFogf(GL_FOG_START, distance * 0.05f); + glFogf(GL_FOG_END, min(distance, 16 * 16 * .75f) * .5f); + } + } + + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT, GL_AMBIENT); + +} + +FloatBuffer *GameRenderer::getBuffer(float a, float b, float c, float d) +{ + lb->clear(); + lb->put(a)->put(b)->put(c)->put(d); + lb->flip(); + return lb; +} + +int GameRenderer::getFpsCap(int option) +{ + int maxFps = 200; + if (option == 1) maxFps = 120; + if (option == 2) maxFps = 35; + return maxFps; +} + +void GameRenderer::updateAllChunks() +{ +// mc->levelRenderer->updateDirtyChunks(mc->cameraTargetPlayer, true); +} |
