public void Normal_Render(Vector3 vertexScale) { for (int z = 0; z < mNumPatchesPerSize; ++z) { for (int x = 0; x < mNumPatchesPerSize; ++x) { CGeommPatch patch = GetPatch(x, z); if (null == patch) { continue; } Profiler.BeginSample("NormalRender.Reset"); patch.Reset(); Profiler.EndSample(); Profiler.BeginSample("NormalRender.Render"); patch.Render(mHeightData, vertexScale); Profiler.EndSample(); Profiler.BeginSample("NormalRender.Present"); patch.Present(); Profiler.EndSample(); } } }
private bool CanDrawMidVertex(int lod, CGeommPatch neighborPatch) { bool ret = false; if (null == neighborPatch || neighborPatch.mLOD <= lod || !neighborPatch.mbIsVisible) { ret = true; } return(ret); }
public void DrawGizoms(Vector3 vertexScale, float gizmosScale, Color gizmosColor) { Gizmos.color = gizmosColor; for (int z = 0; z < mNumPatchesPerSize; ++z) { for (int x = 0; x < mNumPatchesPerSize; ++x) { CGeommPatch patch = GetPatch(x, z); if (null == patch) { continue; } patch.DrawGizoms(mHeightData, vertexScale, gizmosScale); } } }
public void CLOD_Render(Vector3 vectorScale) { for (int z = 0; z < mNumPatchesPerSize; ++z) { for (int x = 0; x < mNumPatchesPerSize; ++x) { CGeommPatch patch = GetPatch(x, z); if (null == patch) { continue; } int curPatchLOD = patch.mLOD; CGeommPatch leftNeighborPatch = GetPatch(x - 1, z); CGeommPatch topNeighborPatch = GetPatch(x, z + 1); CGeommPatch rightNeighborPatch = GetPatch(x + 1, z); CGeommPatch bottomNeighborPatch = GetPatch(x, z - 1); //需要画左边中间的点 patch.mbDrawLeftBorderMid = CanDrawMidVertex(curPatchLOD, leftNeighborPatch); patch.mbDrawTopBorderMid = CanDrawMidVertex(curPatchLOD, topNeighborPatch); patch.mbDrawRightBorderMid = CanDrawMidVertex(curPatchLOD, rightNeighborPatch); patch.mbDrawBottomBorderMid = CanDrawMidVertex(curPatchLOD, bottomNeighborPatch); Profiler.BeginSample("Geomipmapping.Reset"); patch.Reset(); Profiler.EndSample(); if (patch.mbIsVisible) { Profiler.BeginSample("Geomipmapping.RenderPatch"); RenderPatch(patch, vectorScale); Profiler.EndSample(); } Profiler.BeginSample("Geomipmapping.Present"); patch.Present(); Profiler.EndSample(); } } }
private void RenderFan(int inPatchX, int inPatchZ, int fanSize, bool drawLeft, bool drawTop, bool drawRight, bool drawBottom, CGeommPatch patch, Vector3 vectorScale) { if (null == patch) { return; } float fHalfSize = fanSize / 2.0f; int iHalfSize = (int)fHalfSize; //在Patch里面的顶点位置 int xCenterInPatchVertexs = (int)inPatchX; int zCenterInPatchVertexs = (int)inPatchZ; int xLeftInPatchVertexs = xCenterInPatchVertexs - iHalfSize; int zTopInPatchVertexs = zCenterInPatchVertexs + iHalfSize; int xRightInPatchVertexs = xCenterInPatchVertexs + iHalfSize; int zBottomInPatchVertexs = zCenterInPatchVertexs - iHalfSize; //相对于Patch中心点的偏移 int xOffsetFromPatchCentexX = xCenterInPatchVertexs - patch.CenterXInPatch; int zOffsetFromPatchCentexZ = zCenterInPatchVertexs - patch.CenterZInPatch; //在高度图里面的位置 float fanCenterRawXInHeight = patch.PatchCenterXInHeight + xOffsetFromPatchCentexX; float fanCenterRawZInHeight = patch.PatchCenterZInHeight + zOffsetFromPatchCentexZ; float fanLeftRawXInHeight = fanCenterRawXInHeight - iHalfSize; float fanRightRawXInHeight = fanCenterRawXInHeight + iHalfSize; float fanTopRawZInHeight = fanCenterRawZInHeight + iHalfSize; float fanBottomRawZInHeight = fanCenterRawZInHeight - iHalfSize; float fTexLeft = ((float)Mathf.Abs(fanCenterRawXInHeight - fHalfSize) / mHeightData.mSize); float fTexBottom = ((float)Mathf.Abs(fanCenterRawZInHeight - fHalfSize) / mHeightData.mSize); float fTexRight = ((float)Mathf.Abs(fanCenterRawXInHeight + fHalfSize) / mHeightData.mSize); float fTexTop = ((float)Mathf.Abs(fanCenterRawZInHeight + fHalfSize) / mHeightData.mSize); float fMidX = ((fTexLeft + fTexRight) / 2); float fMidZ = ((fTexBottom + fTexTop) / 2); stVertexAtrribute centerVertex = GenerateVertex(GetPatchVertexIndex(xCenterInPatchVertexs, zCenterInPatchVertexs), fanCenterRawXInHeight, fanCenterRawZInHeight, fMidX, fMidZ, vectorScale); stVertexAtrribute bottomLeftVertex = GenerateVertex(GetPatchVertexIndex(xLeftInPatchVertexs, zBottomInPatchVertexs), fanLeftRawXInHeight, fanBottomRawZInHeight, fTexLeft, fTexBottom, vectorScale); stVertexAtrribute leftMidVertex = GenerateVertex(GetPatchVertexIndex(xLeftInPatchVertexs, zCenterInPatchVertexs), fanLeftRawXInHeight, fanCenterRawZInHeight, fTexLeft, fMidZ, vectorScale); stVertexAtrribute topLeftVertex = GenerateVertex(GetPatchVertexIndex(xLeftInPatchVertexs, zTopInPatchVertexs), fanLeftRawXInHeight, fanTopRawZInHeight, fTexLeft, fTexTop, vectorScale); stVertexAtrribute topMidVertex = GenerateVertex(GetPatchVertexIndex(xCenterInPatchVertexs, zTopInPatchVertexs), fanCenterRawXInHeight, fanTopRawZInHeight, fMidX, fTexTop, vectorScale); stVertexAtrribute topRightVertex = GenerateVertex(GetPatchVertexIndex(xRightInPatchVertexs, zTopInPatchVertexs), fanRightRawXInHeight, fanTopRawZInHeight, fTexRight, fTexTop, vectorScale); stVertexAtrribute rightMidVertex = GenerateVertex(GetPatchVertexIndex(xRightInPatchVertexs, zCenterInPatchVertexs), fanRightRawXInHeight, fanCenterRawZInHeight, fTexRight, fMidZ, vectorScale); stVertexAtrribute bottomRightVertex = GenerateVertex(GetPatchVertexIndex(xRightInPatchVertexs, zBottomInPatchVertexs), fanRightRawXInHeight, fanBottomRawZInHeight, fTexRight, fTexBottom, vectorScale); stVertexAtrribute bottomMidVertex = GenerateVertex(GetPatchVertexIndex(xCenterInPatchVertexs, zBottomInPatchVertexs), fanCenterRawXInHeight, fanBottomRawZInHeight, fMidX, fTexBottom, vectorScale); patch.RenderFan( centerVertex, bottomLeftVertex, leftMidVertex, topLeftVertex, topMidVertex, topRightVertex, rightMidVertex, bottomRightVertex, bottomMidVertex, drawLeft, drawTop, drawRight, drawBottom ); }
public void RenderPatch(CGeommPatch patch, Vector3 vectorScale) { if (null == patch) { return; } int iSize = mPatchSize; int iDivisor = mPatchSize - 1; int tLOD = patch.mLOD; while (tLOD >= 0) { iDivisor = iDivisor >> 1; tLOD--; } iSize /= iDivisor; int iHalfSize = iSize / 2; //Patch是从左往右,从下到上,而不是先中心点开始绘制的 for (int inPatchZ = iHalfSize; (inPatchZ + iHalfSize) < mPatchSize + 1; inPatchZ += iSize) { for (int inPatchX = iHalfSize; (inPatchX + iHalfSize) < mPatchSize + 1; inPatchX += iSize) { bool bDrawLeft = false; bool bDrawTop = false; bool bDrawRight = false; bool bDrawBottom = false; //最左边的Fan if (inPatchX == iHalfSize) { bDrawLeft = patch.mbDrawLeftBorderMid; } else { bDrawLeft = true; //如果是内部的Fan,即中点必须画 } if (inPatchZ == iHalfSize) { bDrawBottom = patch.mbDrawBottomBorderMid; } else { bDrawBottom = true; //如果是内部的Fan,即中点必须画 } if (inPatchX >= (mPatchSize - 1 - iHalfSize)) //左边括号的那坨东西是代表最后一个顶点 { bDrawRight = patch.mbDrawRightBorderMid; } else { bDrawRight = true; //如果是内部的Fan,即中点必须画 } if (inPatchZ >= (mPatchSize - 1 - iHalfSize)) { bDrawTop = patch.mbDrawTopBorderMid; } else { bDrawTop = true; //如果是内部的Fan,即中点必须画 } Profiler.BeginSample("Geomipmapping.RenderFan"); RenderFan(inPatchX, inPatchZ, iSize, bDrawLeft, bDrawTop, bDrawRight, bDrawBottom, patch, vectorScale); Profiler.EndSample(); } } }
/// <summary> /// 每条边有多少个顶点 /// </summary> /// <param name="oneSideVertexPerPatch"></param> public void ConfigGeommaping( int vertexPerPatch, GameObject patchPrefab, GameObject patchParent, Texture2D colorTexture, Texture2D detailTexture) { if (vertexPerPatch > 0 && mHeightData.IsValid()) { mPatchSize = vertexPerPatch; int tDivisor = vertexPerPatch - 1; int tLOD = 0; while (tDivisor > 2) { tDivisor = tDivisor >> 1; tLOD++; } mMaxLOD = tLOD; //构造材质 Shader terrainShader = Shader.Find("Terrain/Geomipmapping/TerrainRender"); if (terrainShader != null) { mTerrainMaterial = new Material(terrainShader); if (mTerrainMaterial != null) { mTerrainMaterial.SetTexture("_MainTex", colorTexture); if (detailTexture != null) { mTerrainMaterial.SetTexture("_DetailTex", detailTexture); } } } for (int z = 0; z < mNumPatchesPerSize; z++) { for (int x = 0; x < mNumPatchesPerSize; x++) { GameObject patchGo = GameObject.Instantiate(patchPrefab, Vector3.zero, Quaternion.identity) as GameObject; if (patchGo != null) { patchGo.name = string.Format("{0}_{1:D2}{2:D2}", patchGo.name, x, z); patchGo.transform.SetParent(patchParent.transform); } CGeommPatch patch = new CGeommPatch( x, z, mPatchSize, mMaxLOD, patchGo, mTerrainMaterial ); mGeommPatchs.Add(patch); } } } }
public void UpdatePatch(Camera viewCamera, Vector3 vectorScale, List <float> lodLevels, bool isFrustumCull) { if (null == viewCamera) { Debug.LogError("[UpdatePatch]View Camera is Null!"); return; } if (null == lodLevels || 0 == lodLevels.Count) { Debug.LogError("[UpdatePatch]LOD Levels is Null!"); return; } Profiler.BeginSample("Geomipmapping.CalculateFrustumPlanes"); Plane[] frustumPlanes = GeometryUtility.CalculateFrustumPlanes(viewCamera); Profiler.EndSample(); for (int z = 0; z < mNumPatchesPerSize; z++) { for (int x = 0; x < mNumPatchesPerSize; x++) { CGeommPatch patch = GetPatch(x, z); if (null == patch) { continue; } bool patchIsVisible = true; if (frustumPlanes != null) { Profiler.BeginSample("Geomipmapping.TestPlanesAABB"); patchIsVisible = GeometryUtility.TestPlanesAABB(frustumPlanes, patch.PatchBounds); Profiler.EndSample(); } patch.mbIsVisible = patchIsVisible || !isFrustumCull; if (patch.mbIsVisible) { float patchCenterX = patch.PatchCenterXInHeight * vectorScale.x; float patchCenterZ = patch.PatchCenterZInHeight * vectorScale.z; float patchCenterY = mHeightData.GetRawHeightValue(patch.PatchCenterXInHeight, patch.PatchCenterZInHeight) * vectorScale.y; Profiler.BeginSample("Geomipmapping.CalcDistance"); patch.mDistance = Mathf.Sqrt( Mathf.Pow(viewCamera.transform.position.x - patchCenterX, 2) + Mathf.Pow(viewCamera.transform.position.y - patchCenterY, 2) + Mathf.Pow(viewCamera.transform.position.z - patchCenterZ, 2) ); Profiler.EndSample(); patch.mLOD = mMaxLOD; for (int i = 0; i < lodLevels.Count; ++i) { float lodDistance = lodLevels[i]; if (patch.mDistance < lodDistance) { patch.mLOD = i; break; } } } } } }