/** * Initialize the RHI for this rendering resource */ void InitRHI() override { const int32 NumVerts = 8; TResourceArray<FVector4, VERTEXBUFFER_ALIGNMENT> Verts; Verts.SetNumUninitialized(NumVerts); for (uint32 Z = 0; Z < 2; Z++) { for (uint32 Y = 0; Y < 2; Y++) { for (uint32 X = 0; X < 2; X++) { const FVector4 Vertex = FVector4( (X ? -1 : 1), (Y ? -1 : 1), (Z ? -1 : 1), 1.0f ); Verts[GetCubeVertexIndex(X, Y, Z)] = Vertex; } } } uint32 Size = Verts.GetResourceDataSize(); // Create vertex buffer. Fill buffer with initial data upon creation FRHIResourceCreateInfo CreateInfo(&Verts); VertexBufferRHI = RHICreateVertexBuffer(Size, BUF_Static, CreateInfo); }
static void IssueProjectedShadowOcclusionQuery(FRHICommandListImmediate& RHICmdList, FViewInfo& View, const FProjectedShadowInfo& ProjectedShadowInfo, FOcclusionQueryVS* VertexShader, int32 NumBufferedFrames) { FSceneViewState* ViewState = (FSceneViewState*)View.State; const uint32 QueryIndex = FOcclusionQueryHelpers::GetQueryIssueIndex(ViewState->PendingPrevFrameNumber, NumBufferedFrames); FSceneViewState::ShadowKeyOcclusionQueryMap& ShadowOcclusionQueryMap = ViewState->ShadowOcclusionQueryMaps[QueryIndex]; // The shadow transforms and view transforms are relative to different origins, so the world coordinates need to // be translated. const FVector4 PreShadowToPreViewTranslation(View.ViewMatrices.PreViewTranslation - ProjectedShadowInfo.PreShadowTranslation,0); // If the shadow frustum is farther from the view origin than the near clipping plane, // it can't intersect the near clipping plane. const bool bIntersectsNearClippingPlane = ProjectedShadowInfo.ReceiverFrustum.IntersectSphere( View.ViewMatrices.ViewOrigin + ProjectedShadowInfo.PreShadowTranslation, View.NearClippingDistance * FMath::Sqrt(3.0f) ); if( !bIntersectsNearClippingPlane ) { // Allocate an occlusion query for the primitive from the occlusion query pool. const FRenderQueryRHIRef ShadowOcclusionQuery = ViewState->OcclusionQueryPool.AllocateQuery(); VertexShader->SetParameters(RHICmdList, View); // Draw the primitive's bounding box, using the occlusion query. RHICmdList.BeginRenderQuery(ShadowOcclusionQuery); void* VerticesPtr; void* IndicesPtr; // preallocate memory to fill out with vertices and indices RHICmdList.BeginDrawIndexedPrimitiveUP(PT_TriangleList, 12, 8, sizeof(FVector), VerticesPtr, 0, NUM_CUBE_VERTICES, sizeof(uint16), IndicesPtr); FVector* Vertices = (FVector*)VerticesPtr; uint16* Indices = (uint16*)IndicesPtr; // Generate vertices for the shadow's frustum. for(uint32 Z = 0;Z < 2;Z++) { for(uint32 Y = 0;Y < 2;Y++) { for(uint32 X = 0;X < 2;X++) { const FVector4 UnprojectedVertex = ProjectedShadowInfo.InvReceiverMatrix.TransformFVector4( FVector4( (X ? -1.0f : 1.0f), (Y ? -1.0f : 1.0f), (Z ? 1.0f : 0.0f), 1.0f ) ); const FVector ProjectedVertex = UnprojectedVertex / UnprojectedVertex.W + PreShadowToPreViewTranslation; Vertices[GetCubeVertexIndex(X,Y,Z)] = ProjectedVertex; } } } // we just copy the indices right in FMemory::Memcpy(Indices, GCubeIndices, sizeof(GCubeIndices)); FSceneViewState::FProjectedShadowKey Key(ProjectedShadowInfo); checkSlow(ShadowOcclusionQueryMap.Find(Key) == NULL); ShadowOcclusionQueryMap.Add(Key, ShadowOcclusionQuery); RHICmdList.EndDrawIndexedPrimitiveUP(); RHICmdList.EndRenderQuery(ShadowOcclusionQuery); } }