void CAdvWater::Draw(bool useBlending) { if (!mapInfo->water.forceRendering && (readmap->currMinHeight > 1.0f)) { return; } float3 base = camera->CalcPixelDir(globalRendering->viewPosX, globalRendering->viewSizeY); float3 dv = camera->CalcPixelDir(globalRendering->viewPosX, 0) - camera->CalcPixelDir(globalRendering->viewPosX, globalRendering->viewSizeY); float3 dh = camera->CalcPixelDir(globalRendering->viewPosX + globalRendering->viewSizeX, 0) - camera->CalcPixelDir(globalRendering->viewPosX, 0); float3 xbase; const int numDivs = 20; base *= numDivs; float maxY = -0.1f; float yInc = 1.0f / numDivs; float screenY = 1; unsigned char col[4]; col[0] = (unsigned char)(waterSurfaceColor.x * 255); col[1] = (unsigned char)(waterSurfaceColor.y * 255); col[2] = (unsigned char)(waterSurfaceColor.z * 255); glDisable(GL_ALPHA_TEST); if (useBlending) { glEnable(GL_BLEND); } else { glDisable(GL_BLEND); } glDepthMask(0); glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, bumpTexture); GLfloat plan[] = {0.02f, 0, 0, 0}; glTexGeni(GL_S,GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_S,GL_EYE_PLANE, plan); glEnable(GL_TEXTURE_GEN_S); GLfloat plan2[] = {0, 0, 0.02f, 0}; glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_T, GL_EYE_PLANE, plan2); glEnable(GL_TEXTURE_GEN_T); glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, reflectTexture); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, waterFP); glEnable(GL_FRAGMENT_PROGRAM_ARB); float3 forward = camera->forward; forward.y = 0; forward.ANormalize(); glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, forward.z, forward.x, 0, 0); glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, -forward.x, forward.z, 0, 0); CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(5*numDivs*(numDivs + 1)*2, 5*numDivs, VA_SIZE_TC); //! alloc room for all vertexes and strips float3 dir, zpos; for (int a = 0; a < 5; ++a) { //! CAUTION: loop count must match EnlargeArrays above bool maxReached = false; for (int y = 0; y < numDivs; ++y) { dir = base; dir.ANormalize(); if (dir.y >= maxY) { maxReached = true; break; } xbase = base; for (int x = 0; x < numDivs + 1; ++x) { //! CAUTION: loop count must match EnlargeArrays above dir = xbase + dv; dir.ANormalize(); zpos = camera->pos + dir*(camera->pos.y / -dir.y); zpos.y = sin(zpos.z*0.1f + gs->frameNum*0.06f)*0.06f + 0.05f; col[3] = (unsigned char)((0.8f + 0.7f*dir.y)*255); va->AddVertexQTC(zpos, x*(1.0f/numDivs), screenY - yInc, col); dir = xbase; dir.ANormalize(); zpos = camera->pos + dir*(camera->pos.y / -dir.y); zpos.y = sin(zpos.z*0.1f + gs->frameNum*0.06f)*0.06f + 0.05f; col[3] = (unsigned char)((0.8f + 0.7f*dir.y)*255); va->AddVertexQTC(zpos, x*(1.0f/numDivs), screenY, col); xbase += dh; } va->EndStripQ(); base += dv; screenY -= yInc; } if (!maxReached) { break; } dv *= 0.5f; maxY *= 0.5f; yInc *= 0.5f; } va->DrawArrayTC(GL_TRIANGLE_STRIP); glDepthMask(1); glDisable(GL_FRAGMENT_PROGRAM_ARB); glActiveTextureARB(GL_TEXTURE1_ARB); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glActiveTextureARB(GL_TEXTURE0_ARB); if (!useBlending) { // for translucent stuff like water, the default mode is blending and alpha testing enabled glEnable(GL_BLEND); } }