# 案例研究-在具有不同效能的裝置間調整 Datascape

Datascape 是在 Microsoft 內部開發的 Windows Mixed Reality 應用程式，我們著重于將天氣資料顯示在地形資料上方。 應用程式會利用全像資料視覺效果，來探索使用者在混合現實中探索資料所得到的獨特見解。

## 幾何雲端

``````v2g vert (appdata v)
{
v2g o;
o.height = tex2Dlod(_MainTex, float4(v.uv, 0, 0)).x;
o.vertex = v.vertex;
return o;
}

g2f GetOutput(v2g input, float heightDirection)
{
g2f ret;
float4 newBaseVert = input.vertex;
newBaseVert.y += input.height * heightDirection * _HeigthScale;
ret.vertex = UnityObjectToClipPos(newBaseVert);
ret.height = input.height;
return ret;
}

[maxvertexcount(6)]
void geo(triangle v2g p[3], inout TriangleStream<g2f> triStream)
{
float heightTotal = p[0].height + p[1].height + p[2].height;
if (heightTotal > 0)
{
triStream.Append(GetOutput(p[0], 1));
triStream.Append(GetOutput(p[1], 1));
triStream.Append(GetOutput(p[2], 1));

triStream.RestartStrip();

triStream.Append(GetOutput(p[2], -1));
triStream.Append(GetOutput(p[1], -1));
triStream.Append(GetOutput(p[0], -1));
}
}
fixed4 frag (g2f i) : SV_Target
{
clip(i.height - 0.1f);

float3 finalColor = lerp(_LowColor, _HighColor, i.height);
return float4(finalColor, 1);
}
``````

## 穩固的粒子雲

``````ComputeBuffer cloudPointBuffer = new ComputeBuffer(6, quadPointsStride);
cloudPointBuffer.SetData(new[]
{
new Vector2(-.5f, .5f),
new Vector2(.5f, .5f),
new Vector2(.5f, -.5f),
new Vector2(.5f, -.5f),
new Vector2(-.5f, -.5f),
new Vector2(-.5f, .5f)
});

StructuredBuffer<float3> particlePositions;
v2f vert(uint id : SV_VertexID, uint inst : SV_InstanceID)
{
// Find the center of the quad, from local to world space
float4 centerPoint = mul(unity_ObjectToWorld, float4(particlePositions[inst], 1));

// Calculate y offset for each quad point
float3 cameraForward = normalize(centerPoint - _WorldSpaceCameraPos);

// Read out the particle data
float height = ...;

// Set the position of the vert
o.pos = mul(UNITY_MATRIX_VP, float4(finalPos.xyz, 1));

return o;
}
``````

## 以較低的解析度呈現關閉畫面

``````cloudBlendingCommand = new CommandBuffer();

cloudCamera.CopyFrom(Camera.main);
cloudCamera.rect = new Rect(0, 0, 1, 1);    //Adaptive rendering can set the main camera to a smaller rect
cloudCamera.clearFlags = CameraClearFlags.Color;
cloudCamera.backgroundColor = new Color(0, 0, 0, 1);

currentCloudTexture = RenderTexture.GetTemporary(Camera.main.pixelWidth / 2, Camera.main.pixelHeight / 2, 0);
cloudCamera.targetTexture = currentCloudTexture;

// Render clouds to the offscreen buffer
cloudCamera.Render();
cloudCamera.targetTexture = null;

// Blend low-res clouds to the main target
cloudBlendingCommand.Blit(currentCloudTexture, new RenderTargetIdentifier(BuiltinRenderTextureType.CurrentActive), blitMaterial);
``````

## 剔除粒子

``````AppendStructuredBuffer<int> culledParticleIdx;

if (show)
culledParticleIdx.Append(id.x);
``````

C # 程式碼：

``````protected void Awake()
{
// Create an append buffer, setting the maximum size and the contents stride length
culledParticlesIdxBuffer = new ComputeBuffer(ParticleCount, sizeof(int), ComputeBufferType.Append);

// Set up Args Buffer for Draw Procedural Indirect
argsBuffer = new ComputeBuffer(4, sizeof(int), ComputeBufferType.IndirectArguments);
argsBuffer.SetData(new int[] { DataVertCount, 0, 0, 0 });
}

protected void Update()
{
// Reset the append buffer, and dispatch the compute shader normally
culledParticlesIdxBuffer.SetCounterValue(0);

computer.Dispatch(...)

// Copy the append buffer count into the args buffer used by the Draw Procedural Indirect call
ComputeBuffer.CopyCount(culledParticlesIdxBuffer, argsBuffer, dstOffset: 1);
ribbonRenderCommand.DrawProceduralIndirect(Matrix4x4.identity, renderMaterial, 0, MeshTopology.Triangles, dataBuffer);
}
``````

## 關於作者

 Robert Ferrese軟體工程師 @Microsoft Dan Andersson軟體工程師 @Microsoft