⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 terrrender.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
                  buildLightTri(&lightTris[j], &mTerrainLights[i]);
               }

               start += count;
            } else {
               AssertFatal(mXFIndexBuffer[start] == GL_TRIANGLES, "Error, bad start code!");
               start++;
               U32 count = mXFIndexBuffer[start];
               AssertFatal((count / 3) * 3 == count, "Error, vertex count not divisible by 3!");

               U32 triCount = count/3;
               LightTriangle* lightTris = (LightTriangle*)FrameAllocator::alloc(sizeof(LightTriangle) * triCount);
               U32 j;
               for (j = 0; j < (triCount-1); j++)
                  lightTris[j].next = &lightTris[j+1];
               lightTris[triCount-1].next = sgCurrLightTris;
               sgCurrLightTris = lightTris;

               // Copy out tri data here...
               for (j = 0; j <  triCount; j++) {
                  lightTris[j].point1 = mXFVertices[mXFIndexBuffer[start + 1 + (j*3) + 0]];
                  lightTris[j].point2 = mXFVertices[mXFIndexBuffer[start + 1 + (j*3) + 1]];
                  lightTris[j].point3 = mXFVertices[mXFIndexBuffer[start + 1 + (j*3) + 2]];

                  buildLightTri(&lightTris[j], &mTerrainLights[i]);
               }

               start += count;
            }
         }
      }
   }
}

/*void TerrainRender::drawTriFan(U32 vCount, U32 *indexBuffer)
{
   glBegin(GL_LINES);
   U32 cur = vCount - 1;
   for(U32 i = 1; i < vCount; i++)
   {
      glArrayElement(indexBuffer[0]);
      glArrayElement(indexBuffer[cur]);
      glArrayElement(indexBuffer[cur]);
      glArrayElement(indexBuffer[i]);
      cur = i;
   }
   glEnd();
}*/

void TerrainRender::renderXFCache()
{
   U32 count = 0;

   while (count < mXFIndexCount)
   {
      U32 mode = mXFIndexBuffer[count];
      U32 vertexCount = mXFIndexBuffer[count + 1];
      glDrawElements(mode, vertexCount, GL_UNSIGNED_SHORT, mXFIndexBuffer + count + 2);
      count += vertexCount + 2;
   }
}

void doTexGens(Point4F &s, Point4F &t)
{
   EdgePoint *pt = mXFVertices;
   EdgePoint *last = pt + mXFPointCount;
   for(;pt < last; pt++)
   {
      pt->haze = pt->x * s.x + pt->y * s.y + pt->z * s.z + s.w;
      pt->distance = pt->x * t.x + pt->y * t.y + pt->z * t.z + t.w;
   }
}

#ifdef TORQUE_OS_WIN32
void TerrainRender::renderD3DBumps(Point2F bumpTextureOffset)
{
    PROFILE_START(TerrainRenderBumpsD3D);

    glColor3f(1.0,1.0,1.0);
    //First pass - normal bump map, no blending, no offset
    doTexGens(bumpTexGenS, bumpTexGenT);
    glBindTexture(GL_TEXTURE_2D, mCurrentBlock->mBumpTextureHandle.getGLName());
    renderXFCache();

    //Second pass - inverted bump map, additive blending, offset
    Point4F bumpTexGenOS = bumpTexGenS;
    Point4F bumpTexGenOT = bumpTexGenT;
    bumpTexGenOS.w += bumpTextureOffset.x;
    bumpTexGenOT.w += bumpTextureOffset.y;
    doTexGens(bumpTexGenOS, bumpTexGenOT);

    glBindTexture(GL_TEXTURE_2D, mCurrentBlock->mInvertedBumpTextureHandle.getGLName());
    glBlendFunc(GL_ONE, GL_ONE);
    glEnable(GL_BLEND);
    renderXFCache();

    //Setup blending for the terrain pass
    glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);

    PROFILE_END();
}
#endif

void TerrainRender::renderGLBumps(Point2F bumpTextureOffset, U32 hazeName)
{
    PROFILE_START(TerrainRenderBumpsGL);
    //have to set color to white or bumps turn up black on the terrain
    glColor3f(1.0,1.0,1.0);
    doTexGens(bumpTexGenS, bumpTexGenT);

    //Set up TMU #0
    //Normal bump texture
    glBindTexture(GL_TEXTURE_2D, mCurrentBlock->mBumpTextureHandle.getGLName());
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);

    //Set up TMU #1
    //Inverted bump texture
    //Offset the texture matrix
    glActiveTextureARB(GL_TEXTURE1_ARB);
    glClientActiveTextureARB(GL_TEXTURE1_ARB);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, mCurrentBlock->mInvertedBumpTextureHandle.getGLName());
    glTexCoordPointer(2, GL_FLOAT, sizeof(EdgePoint), &mXFVertices->haze);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
    glMatrixMode(GL_TEXTURE);
    glPushMatrix();
    glTranslatef(bumpTextureOffset.x, bumpTextureOffset.y, 0.0);

    //Render!
    renderXFCache();

    //Restore TMU #1
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    glBindTexture(GL_TEXTURE_2D, hazeName);
    glTexCoordPointer(2, GL_FLOAT, sizeof(EdgePoint), &mXFVertices->fogRed);

    //Restore TMU #0
    glActiveTextureARB(GL_TEXTURE0_ARB);
    glClientActiveTextureARB(GL_TEXTURE0_ARB);

    //Set up for the bump mapping application
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glEnable(GL_BLEND);
    //Do the rest in the function
    PROFILE_END();
}

void TerrainRender::renderBlock(TerrainBlock *block, SceneState *state)
{
   PROFILE_START(TerrainRender);
   PROFILE_START(TerrainRenderSetup);
   dglSetRenderPrimType(1);
   U32 storedWaterMark = FrameAllocator::getWaterMark();

   if (sgTextureFreeListPrimed == false) {
      sgTextureFreeListPrimed = true;
      AssertFatal(mTextureFreeList.size() == 0, "Error, unprimed free list should always be size 0");

      mTextureFreeList.setSize(sgFreeListPrimeCount);
      for (U32 i = 0; i < sgFreeListPrimeCount; i++) {
         constructInPlace(&mTextureFreeList[i]);
         mTextureFreeList[i] = TextureHandle((const char*)NULL, mBlendBitmap, TerrainTexture, true);
      }
   }

   mFrameIndex++;
   mSceneState = state;
   mFarDistance = state->getVisibleDistance();

   dglGetModelview(&mCameraToObject);

   mCameraToObject.inverse();

   mCameraToObject.getColumn(3, &mCamPos);
   mFogColor = state->getFogColor();

   TextureHandle hazeTexture = gClientSceneGraph->getFogTexture();
   mCurrentBlock = block;

   Point4F detTexGenS = Point4F(1, 0, 0, 0);
   Point4F detTexGenT = Point4F(0, 1, 0, 0);
   if (mEnableTerrainDetails && mCurrentBlock->mDetailTextureHandle.getGLName() != 0) {
      detTexGenS.x *= 62.0 / mCurrentBlock->mDetailTextureHandle.getWidth();
      detTexGenT.y *= 62.0 / mCurrentBlock->mDetailTextureHandle.getHeight();
      detTexGenS.w = -(S32) (mCamPos.x*detTexGenS.x);
      detTexGenT.w = -(S32) (mCamPos.y*detTexGenT.y);
   }
// CW - stuff with bump maps
    //calculate the texture offset
    if (mEnableTerrainEmbossBumps && mCurrentBlock->mBumpTextureHandle.getGLName() != 0)
    {
        PROFILE_START(TerrainRenderBumpBuild);
        //There should be a better way to do this, really...
#ifdef TORQUE_OS_WIN32
        if (dStrcmp(Con::getVariable( "$pref::Video::displayDevice" ), "OpenGL") == 0)
            mRenderGL = true;
        else
            mRenderGL = false;
#endif
        //note: don't multiply light by inverse modelview matrix
        //because it is already in object space (or world or anything, really)
        //The first light in the light manager is always the sun.
        //This is also how players are lit, so if this is broken, that is broken as well.

        Point3F sTangent,tTangent;
	//celestial
//        VectorF sunVector = gClientSceneGraph->getLightManager()->getShadowLightDirection();
        VectorF sunVector;
		if(gCelestials == NULL)
			sunVector = gClientSceneGraph->getLightManager()->getShadowLightDirection();
		else
			sunVector = gCelestials->mSunVector;
	//celestial end

        //find s and t tangents
        F32 pHeight[4];
        for (int i = 0; i < 4; i++)
        {
            int x = i == 0 || i == 3 ? 0 : 255;
            int y = i == 1 || i == 2 ? 0 : 255;
            block->getHeight(Point2F(x,y), &pHeight[i]);
        }

        S32 pSquareSize = block->getSquareSize();
        sTangent.x = pSquareSize;
        sTangent.y = pHeight[3] - pHeight[0];
        sTangent.z = 0;
        tTangent.x = 0;
        tTangent.y = pHeight[1] - pHeight[0];
        tTangent.z = pSquareSize;
        sTangent.normalize();
        tTangent.normalize();

        // The above is needed for both emboss and dot3 bump mapping
        // techniques.  However, the below 2 lines are emboss-specific.
        // So, dot3 bump mapping would not be too difficult because
        // I have already computed most of the necessary info.
        bumpTextureOffset.x = mDot(sTangent, sunVector) * mCurrentBlock->mBumpOffset;
        bumpTextureOffset.y = mDot(tTangent, sunVector) * mCurrentBlock->mBumpOffset;
        PROFILE_END();
    }
// CW - end bump map stuff
   mSquareSize = block->getSquareSize();

//   mNewGenTextureCount = 0;

   // compute pixelError
   if(mScreenError >= 0.001)
      mPixelError = 1 / dglProjectRadius(mScreenError, 1);
   else
      mPixelError = 0.000001;

   buildClippingPlanes(state->mFlipCull);
   buildLightArray();

   F32 worldToScreenScale   = dglProjectRadius(1,1);
   F32 zeroDetailDistance   = (mSquareSize * worldToScreenScale) / (1 << 6) - (mSquareSize >> 1);
   F32 zeroBumpDistance      = (mSquareSize * worldToScreenScale) / (1 << mCurrentBlock->mZeroBumpScale) - (mSquareSize >> 1);

   F32 blockSize = mSquareSize * TerrainBlock::BlockSquareWidth;

   S32 xStart;
   S32 xEnd;
   S32 yStart;
   S32 yEnd;

   if(mCurrentBlock->mTile)
   {
      xStart = (S32)mFloor( (mCamPos.x - mFarDistance) / blockSize );
      xEnd   = (S32)mCeil ( (mCamPos.x + mFarDistance) / blockSize );
      yStart = (S32)mFloor( (mCamPos.y - mFarDistance) / blockSize );
      yEnd   = (S32)mCeil ( (mCamPos.y + mFarDistance) / blockSize );
   }
   else
   {
      xStart = 0;
      xEnd   = 1;
      yStart = 0;
      yEnd   = 1;
   }

   S32 xExt   = (S32)(xEnd - xStart);
   S32 yExt   = (S32)(yEnd - yStart);

   PROFILE_END();
   PROFILE_START(TerrainRenderRecurse);
   F32 height = fixedToFloat(block->getHeight(0,0));

   EdgeParent **bottomEdges = (EdgeParent **) FrameAllocator::alloc(sizeof(ChunkScanEdge *) * xExt);
   TerrainRender::allocRenderEdges(xExt, bottomEdges, false);
   ChunkCornerPoint *prevCorner = TerrainRender::allocInitialPoint(Point3F(xStart * blockSize, yStart * blockSize, height));

   mTerrainOffset.set(xStart * TerrainBlock::BlockSquareWidth, yStart * TerrainBlock::BlockSquareWidth);

   for(S32 x = 0; x < xExt; x++)
   {
      bottomEdges[x]->p1 = prevCorner;
      prevCorner = TerrainRender::allocInitialPoint(Point3F((xStart + x ) * blockSize, yStart * blockSize, height));
      bottomEdges[x]->p2 = prevCorner;
   }
   for(S32 y = 0; y < yExt; y++)
   {
      // allocate the left edge:
      EdgeParent *left;
      TerrainRender::allocRenderEdges(1, &left, false);
      left->p1 = TerrainRender::allocInitialPoint(Point3F(xStart * blockSize, (yStart + y + 1) * blockSize, height));
      left->p2 = bottomEdges[0]->p1;
      for(S32 x = 0; x < xExt; x++)
      {
         EdgeParent *right;
         TerrainRender::allocRenderEdges(1, &right, false);
         right->p1 = TerrainRender::allocInitialPoint(Point3F((xStart + x + 1) * blockSize, (yStart + y + 1) * blockSize, height));
         right->p2 = bottomEdges[x]->p2;
         EdgeParent *top;
         TerrainRender::allocRenderEdges(1, &top, false);
         top->p1 = left->p1;
         top->p2 = right->p1;

         mBlockOffset.set(x << TerrainBlock::BlockShift,
                          y << TerrainBlock::BlockShift);

         mBlockPos.set((xStart + x) * blockSize,
                       (yStart + y) * blockSize);

         TerrainRender::processCurrentBlock(state, top, right, bottomEdges[x], left);
         left = right;
         bottomEdges[x] = top;
      }
   }
   U32 slop = 0;
   AllocatedTexture *fwalk = mTextureFreeListHead.next;
   while(fwalk != &mTextureFreeListTail && slop < mTextureSlopSize)
   {
      fwalk = fwalk->next;
      slop++;
   }
   while(fwalk != &mTextureFreeListTail)
   {
      AllocatedTexture *next = fwalk->next;
      fwalk->unlink();

      S32 x = (fwalk->x & TerrainBlock::BlockMask) >> fwalk->level;
      S32 y = (fwalk->y & TerrainBlock::BlockMask) >> fwalk->level;
      mTextureGridPtr[fwalk->level - 2][x + (y << (8 - fwalk->level))] = NULL;

      freeTerrTexture(fwalk);
      fwalk = next;
   }

   PROFILE_END();
   PROFILE_START(TerrainRenderEmit);

   bool lockArrays = dglDoesSupportCompiledVertexArray() && dglDoesSupportARBMultitexture();
   bool multitextureFog = dglDoesSupportARBMultitexture(); // dc 6-1-01 - this flag is BAD.  The non mtex path doesn't currently work.  !!!!!!TBD
   bool vertexBuffer = dglDoesSupportVertexBuffer() && (block->mVertexBuffer != -1);

   glFrontFace(GL_CW);
   glEnable(GL_CULL_FACE);
   glEnableClientState(GL_VERTEX_ARRAY);

   if(!vertexBuffer)
      mXFVertices = (EdgePoint *) FrameAllocator::alloc(sizeof(EdgePoint) * VertexBufferSize);

    //CW - D3D goes crazy if we stick our bump colors in the EdgePoint structure, so make a new one
    ColorI *bumpColors = (ColorI*)FrameAllocator::alloc(sizeof(ColorI) * VertexBufferSize);

   glVertexPointer(3, GL_FLOAT, sizeof(EdgePoint), mXFVertices);
   glEnable(GL_BLEND);
   glBlendFunc(GL_ONE, GL_ZERO);

  // see if we should setup hazing on the second TMU
   // if not, we'll have to 2-pass the terrain...
   // and that ain't gonna be fast no matter how ya slice it.

   if(multitextureFog)
   {
      // Hazing
      glCl

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -