virtual void SetMesh(FRHICommandList& RHICmdList, FShader* Shader,const FVertexFactory* VertexFactory,const FSceneView& View,const FMeshBatchElement& BatchElement,uint32 DataFlags) const override { const bool bInstanced = View.GetFeatureLevel() >= ERHIFeatureLevel::SM4; FMeshParticleVertexFactory* MeshParticleVF = (FMeshParticleVertexFactory*)VertexFactory; FVertexShaderRHIParamRef VertexShaderRHI = Shader->GetVertexShader(); SetUniformBufferParameter(RHICmdList, VertexShaderRHI, Shader->GetUniformBufferParameter<FMeshParticleUniformParameters>(), MeshParticleVF->GetUniformBuffer() ); if (!bInstanced) { const FMeshParticleVertexFactory::FBatchParametersCPU* BatchParameters = (const FMeshParticleVertexFactory::FBatchParametersCPU*)BatchElement.UserData; const FMeshParticleInstanceVertex* Vertex = BatchParameters->InstanceBuffer + BatchElement.UserIndex; const FMeshParticleInstanceVertexDynamicParameter* DynamicVertex = BatchParameters->DynamicParameterBuffer + BatchElement.UserIndex; SetShaderValue(RHICmdList, VertexShaderRHI, Transform1, Vertex->Transform[0]); SetShaderValue(RHICmdList, VertexShaderRHI, Transform2, Vertex->Transform[1]); SetShaderValue(RHICmdList, VertexShaderRHI, Transform3, Vertex->Transform[2]); SetShaderValue(RHICmdList, VertexShaderRHI, SubUVParams, FVector4((float)Vertex->SubUVParams[0], (float)Vertex->SubUVParams[1], (float)Vertex->SubUVParams[2], (float)Vertex->SubUVParams[3])); SetShaderValue(RHICmdList, VertexShaderRHI, SubUVLerp, Vertex->SubUVLerp); SetShaderValue(RHICmdList, VertexShaderRHI, ParticleDirection, Vertex->Velocity); SetShaderValue(RHICmdList, VertexShaderRHI, RelativeTime, Vertex->RelativeTime); if (BatchParameters->DynamicParameterBuffer) { SetShaderValue(RHICmdList, VertexShaderRHI, DynamicParameter, FVector4(DynamicVertex->DynamicValue[0], DynamicVertex->DynamicValue[1], DynamicVertex->DynamicValue[2], DynamicVertex->DynamicValue[3])); } SetShaderValue(RHICmdList, VertexShaderRHI, ParticleColor, FVector4(Vertex->Color.Component(0), Vertex->Color.Component(1), Vertex->Color.Component(2), Vertex->Color.Component(3))); } }
bool TDistortionMeshDrawingPolicyFactory<DistortMeshPolicy>::DrawDynamicMesh( FRHICommandList& RHICmdList, const FSceneView& View, ContextType bInitializeOffsets, const FMeshBatch& Mesh, bool bBackFace, bool bPreFog, const FPrimitiveSceneProxy* PrimitiveSceneProxy, FHitProxyId HitProxyId ) { const auto FeatureLevel = View.GetFeatureLevel(); bool bDistorted = Mesh.MaterialRenderProxy && Mesh.MaterialRenderProxy->GetMaterial(FeatureLevel)->IsDistorted(); if(bDistorted && !bBackFace) { // draw dynamic mesh element using distortion mesh policy TDistortionMeshDrawingPolicy<DistortMeshPolicy> DrawingPolicy( Mesh.VertexFactory, Mesh.MaterialRenderProxy, *Mesh.MaterialRenderProxy->GetMaterial(FeatureLevel), bInitializeOffsets, View.Family->EngineShowFlags.ShaderComplexity, FeatureLevel ); RHICmdList.BuildAndSetLocalBoundShaderState(DrawingPolicy.GetBoundShaderStateInput(View.GetFeatureLevel())); DrawingPolicy.SetSharedState(RHICmdList, &View, typename TDistortionMeshDrawingPolicy<DistortMeshPolicy>::ContextDataType()); for (int32 BatchElementIndex = 0; BatchElementIndex < Mesh.Elements.Num(); BatchElementIndex++) { DrawingPolicy.SetMeshRenderState(RHICmdList, View,PrimitiveSceneProxy,Mesh,BatchElementIndex,bBackFace,typename TDistortionMeshDrawingPolicy<DistortMeshPolicy>::ElementDataType(), typename TDistortionMeshDrawingPolicy<DistortMeshPolicy>::ContextDataType()); DrawingPolicy.DrawMesh(RHICmdList, Mesh,BatchElementIndex); } return true; } else { return false; } }
void RunBenchmarkShader(FRHICommandList& RHICmdList, const FSceneView& View, TRefCountPtr<IPooledRenderTarget>& Src, float WorkScale) { auto ShaderMap = GetGlobalShaderMap(View.GetFeatureLevel()); TShaderMapRef<FPostProcessBenchmarkVS> VertexShader(ShaderMap); TShaderMapRef<FPostProcessBenchmarkPS<Method> > PixelShader(ShaderMap); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, View, Src); VertexShader->SetParameters(RHICmdList, View); // single pass was not fine grained enough so we reduce the pass size based on the fractional part of WorkScale float TotalHeight = GBenchmarkResolution * WorkScale; // rounds up uint32 PassCount = (uint32)FMath::CeilToFloat(TotalHeight / GBenchmarkResolution); for(uint32 i = 0; i < PassCount; ++i) { float Top = i * GBenchmarkResolution; float Bottom = FMath::Min(Top + GBenchmarkResolution, TotalHeight); float LocalHeight = Bottom - Top; DrawRectangle( RHICmdList, 0, 0, GBenchmarkResolution, LocalHeight, 0, 0, GBenchmarkResolution, LocalHeight, FIntPoint(GBenchmarkResolution, GBenchmarkResolution), FIntPoint(GBenchmarkResolution, GBenchmarkResolution), *VertexShader, EDRF_Default); } }
void FSimpleElementCollector::DrawBatchedElements(FRHICommandList& RHICmdList, const FSceneView& View, FTexture2DRHIRef DepthTexture, EBlendModeFilter::Type Filter) const { // Mobile HDR does not execute post process, so does not need to render flipped const bool bNeedToSwitchVerticalAxis = RHINeedsToSwitchVerticalAxis(View.GetShaderPlatform()) && !bIsMobileHDR; // Draw the batched elements. BatchedElements.Draw( RHICmdList, View.GetFeatureLevel(), bNeedToSwitchVerticalAxis, View.ViewProjectionMatrix, View.ViewRect.Width(), View.ViewRect.Height(), View.Family->EngineShowFlags.HitProxies, 1.0f, &View, DepthTexture, Filter ); }
void FMeshElementCollector::AddMesh(int32 ViewIndex, FMeshBatch& MeshBatch) { checkSlow(MeshBatch.GetNumPrimitives() > 0); checkSlow(MeshBatch.VertexFactory && MeshBatch.MaterialRenderProxy); checkSlow(PrimitiveSceneProxy); if (MeshBatch.bCanApplyViewModeOverrides) { FSceneView* View = Views[ViewIndex]; ApplyViewModeOverrides( ViewIndex, View->Family->EngineShowFlags, View->GetFeatureLevel(), PrimitiveSceneProxy, MeshBatch.bUseWireframeSelectionColoring, MeshBatch, *this); } TArray<FMeshBatchAndRelevance,SceneRenderingAllocator>& ViewMeshBatches = *MeshBatches[ViewIndex]; new (ViewMeshBatches) FMeshBatchAndRelevance(MeshBatch, PrimitiveSceneProxy, FeatureLevel); }
void SetParameters( FRHICommandList& RHICmdList, const FMaterialRenderProxy* MaterialRenderProxy, const FSceneView& View ) { FMeshMaterialShader::SetParameters(RHICmdList, GetPixelShader(), MaterialRenderProxy, *MaterialRenderProxy->GetMaterial(View.GetFeatureLevel()), View, ESceneRenderTargetsMode::SetTextures); float Ratio = View.UnscaledViewRect.Width() / (float)View.UnscaledViewRect.Height(); float Params[4]; Params[0] = View.ViewMatrices.ProjMatrix.M[0][0]; Params[1] = Ratio; Params[2] = (float)View.UnscaledViewRect.Width(); Params[3] = (float)View.UnscaledViewRect.Height(); SetShaderValue(RHICmdList, GetPixelShader(), DistortionParams, Params); }
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy, const float FadeAlphaValue=1.0f) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, View.ViewUniformBuffer, true, ESceneRenderTargetsMode::SetTextures); FTransform ComponentTrans = DecalProxy.ComponentTrans; FMatrix WorldToComponent = ComponentTrans.ToInverseMatrixWithScale(); // Set the transform from screen space to light space. if(SvPositionToDecal.IsBound()) { FVector2D InvViewSize = FVector2D(1.0f / View.ViewRect.Width(), 1.0f / View.ViewRect.Height()); // setup a matrix to transform float4(SvPosition.xyz,1) directly to Decal (quality, performance as we don't need to convert or use interpolator) // new_xy = (xy - ViewRectMin.xy) * ViewSizeAndInvSize.zw * float2(2,-2) + float2(-1, 1); // transformed into one MAD: new_xy = xy * ViewSizeAndInvSize.zw * float2(2,-2) + (-ViewRectMin.xy) * ViewSizeAndInvSize.zw * float2(2,-2) + float2(-1, 1); float Mx = 2.0f * InvViewSize.X; float My = -2.0f * InvViewSize.Y; float Ax = -1.0f - 2.0f * View.ViewRect.Min.X * InvViewSize.X; float Ay = 1.0f + 2.0f * View.ViewRect.Min.Y * InvViewSize.Y; // todo: we could use InvTranslatedViewProjectionMatrix and TranslatedWorldToComponent for better quality const FMatrix SvPositionToDecalValue = FMatrix( FPlane(Mx, 0, 0, 0), FPlane( 0, My, 0, 0), FPlane( 0, 0, 1, 0), FPlane(Ax, Ay, 0, 1) ) * View.InvViewProjectionMatrix * WorldToComponent; SetShaderValue(RHICmdList, ShaderRHI, SvPositionToDecal, SvPositionToDecalValue); } // Set the transform from light space to world space if(DecalToWorld.IsBound()) { const FMatrix DecalToWorldValue = ComponentTrans.ToMatrixWithScale(); SetShaderValue(RHICmdList, ShaderRHI, DecalToWorld, DecalToWorldValue); } SetShaderValue(RHICmdList, ShaderRHI, WorldToDecal, WorldToComponent); float LifetimeAlpha = FMath::Clamp(View.Family->CurrentWorldTime * -DecalProxy.InvFadeDuration + DecalProxy.FadeStartDelayNormalized, 0.0f, 1.0f); SetShaderValue(RHICmdList, ShaderRHI, DecalParams, FVector2D(FadeAlphaValue, LifetimeAlpha)); }
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy, const float FadeAlphaValue=1.0f) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, true, ESceneRenderTargetsMode::SetTextures); FTransform ComponentTrans = DecalProxy.ComponentTrans; FMatrix WorldToComponent = ComponentTrans.ToInverseMatrixWithScale(); // Set the transform from screen space to light space. if(ScreenToDecal.IsBound()) { const FMatrix ScreenToDecalValue = FMatrix( FPlane(1,0,0,0), FPlane(0,1,0,0), FPlane(0,0,View.ViewMatrices.ProjMatrix.M[2][2],1), FPlane(0,0,View.ViewMatrices.ProjMatrix.M[3][2],0) ) * View.InvViewProjectionMatrix * WorldToComponent; SetShaderValue(RHICmdList, ShaderRHI, ScreenToDecal, ScreenToDecalValue); } // Set the transform from light space to world space if(DecalToWorld.IsBound()) { const FMatrix DecalToWorldValue = ComponentTrans.ToMatrixWithScale(); SetShaderValue(RHICmdList, ShaderRHI, DecalToWorld, DecalToWorldValue); } SetShaderValue(RHICmdList, ShaderRHI, FadeAlpha, FadeAlphaValue); SetShaderValue(RHICmdList, ShaderRHI, WorldToDecal, WorldToComponent); }
void RunBenchmarkShader(FRHICommandList& RHICmdList, FVertexBufferRHIParamRef VertexThroughputBuffer, const FSceneView& View, TRefCountPtr<IPooledRenderTarget>& Src, float WorkScale) { auto ShaderMap = GetGlobalShaderMap(View.GetFeatureLevel()); TShaderMapRef<FPostProcessBenchmarkVS<VsMethod>> VertexShader(ShaderMap); TShaderMapRef<FPostProcessBenchmarkPS<PsMethod>> PixelShader(ShaderMap); bool bVertexTest = VsMethod == 1; FVertexDeclarationRHIParamRef VertexDeclaration = bVertexTest ? GVertexThroughputDeclaration.DeclRHI : GFilterVertexDeclaration.VertexDeclarationRHI; static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), BoundShaderState, VertexDeclaration, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, View, Src); VertexShader->SetParameters(RHICmdList, View); if (bVertexTest) { // Vertex Tests uint32 TotalNumPrimitives = FMath::CeilToInt(GBenchmarkPrimitives * WorkScale); uint32 TotalNumVertices = TotalNumPrimitives * 3; while (TotalNumVertices != 0) { uint32 VerticesThisPass = FMath::Min(TotalNumVertices, GBenchmarkVertices); uint32 PrimitivesThisPass = VerticesThisPass / 3; RHICmdList.SetStreamSource(0, VertexThroughputBuffer, sizeof(FBenchmarkVertex), 0); RHICmdList.DrawPrimitive(PT_TriangleList, 0, PrimitivesThisPass, 1); TotalNumVertices -= VerticesThisPass; } } else { // Pixel Tests // single pass was not fine grained enough so we reduce the pass size based on the fractional part of WorkScale float TotalHeight = GBenchmarkResolution * WorkScale; // rounds up uint32 PassCount = (uint32)FMath::CeilToFloat(TotalHeight / GBenchmarkResolution); for (uint32 i = 0; i < PassCount; ++i) { float Top = i * GBenchmarkResolution; float Bottom = FMath::Min(Top + GBenchmarkResolution, TotalHeight); float LocalHeight = Bottom - Top; DrawRectangle( RHICmdList, 0, 0, GBenchmarkResolution, LocalHeight, 0, 0, GBenchmarkResolution, LocalHeight, FIntPoint(GBenchmarkResolution, GBenchmarkResolution), FIntPoint(GBenchmarkResolution, GBenchmarkResolution), *VertexShader, EDRF_Default); } } }
void FSlateRHIRenderingPolicy::DrawElements(FRHICommandListImmediate& RHICmdList, FSlateBackBuffer& BackBuffer, const FMatrix& ViewProjectionMatrix, const TArray<FSlateRenderBatch>& RenderBatches) { SCOPE_CYCLE_COUNTER( STAT_SlateDrawTime ); // Should only be called by the rendering thread check(IsInRenderingThread()); TSlateElementVertexBuffer<FSlateVertex>& VertexBuffer = VertexBuffers[CurrentBufferIndex]; FSlateElementIndexBuffer& IndexBuffer = IndexBuffers[CurrentBufferIndex]; float TimeSeconds = FPlatformTime::Seconds() - GStartTime; float RealTimeSeconds = FPlatformTime::Seconds() - GStartTime; float DeltaTimeSeconds = FApp::GetDeltaTime(); static const FEngineShowFlags DefaultShowFlags(ESFIM_Game); const float DisplayGamma = bGammaCorrect ? GEngine ? GEngine->GetDisplayGamma() : 2.2f : 1.0f; FSceneViewFamilyContext SceneViewContext ( FSceneViewFamily::ConstructionValues ( &BackBuffer, NULL, DefaultShowFlags ) .SetWorldTimes( TimeSeconds, RealTimeSeconds, DeltaTimeSeconds ) .SetGammaCorrection( DisplayGamma ) ); FSceneView* SceneView = NULL; TShaderMapRef<FSlateElementVS> VertexShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); // Disabled stencil test state FDepthStencilStateRHIRef DSOff = TStaticDepthStencilState<false,CF_Always>::GetRHI(); FSamplerStateRHIRef BilinearClamp = TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(); if (GRHISupportsBaseVertexIndex) { RHICmdList.SetStreamSource(0, VertexBuffer.VertexBufferRHI, sizeof(FSlateVertex), 0); } // Draw each element for( int32 BatchIndex = 0; BatchIndex < RenderBatches.Num(); ++BatchIndex ) { const FSlateRenderBatch& RenderBatch = RenderBatches[BatchIndex]; const FSlateShaderResource* ShaderResource = RenderBatch.Texture; const ESlateBatchDrawFlag::Type DrawFlags = RenderBatch.DrawFlags; const ESlateDrawEffect::Type DrawEffects = RenderBatch.DrawEffects; const ESlateShader::Type ShaderType = RenderBatch.ShaderType; const FShaderParams& ShaderParams = RenderBatch.ShaderParams; if( !RenderBatch.CustomDrawer.IsValid() ) { if( !ShaderResource || ShaderResource->GetType() != ESlateShaderResource::Material ) { FSlateElementPS* PixelShader = GetTexturePixelShader(ShaderType, DrawEffects); RHICmdList.SetLocalBoundShaderState(RHICmdList.BuildLocalBoundShaderState( GSlateVertexDeclaration.VertexDeclarationRHI, VertexShader->GetVertexShader(), nullptr, nullptr, PixelShader->GetPixelShader(), FGeometryShaderRHIRef())); VertexShader->SetViewProjection(RHICmdList, ViewProjectionMatrix); #if !DEBUG_OVERDRAW RHICmdList.SetBlendState( (RenderBatch.DrawFlags & ESlateBatchDrawFlag::NoBlending) ? TStaticBlendState<>::GetRHI() : TStaticBlendState<CW_RGBA, BO_Add, BF_SourceAlpha, BF_InverseSourceAlpha, BO_Add, BF_InverseDestAlpha, BF_One>::GetRHI() ); #else RHICmdList.SetBlendState(TStaticBlendState<CW_RGB, BO_Add, BF_One, BF_One, BO_Add, BF_Zero, BF_InverseSourceAlpha>::GetRHI()); #endif // Disable stencil testing by default RHICmdList.SetDepthStencilState(DSOff); if (DrawFlags & ESlateBatchDrawFlag::Wireframe) { RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Wireframe, CM_None, true>::GetRHI()); } else { RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None, true>::GetRHI()); } if (RenderBatch.ScissorRect.IsSet()) { RHICmdList.SetScissorRect(true, RenderBatch.ScissorRect.GetValue().Left, RenderBatch.ScissorRect.GetValue().Top, RenderBatch.ScissorRect.GetValue().Right, RenderBatch.ScissorRect.GetValue().Bottom); } else { RHICmdList.SetScissorRect(false, 0, 0, 0, 0); } FTexture2DRHIRef TextureRHI; if(ShaderResource) { TextureRHI = ((TSlateTexture<FTexture2DRHIRef>*)ShaderResource)->GetTypedResource(); } if (ShaderType == ESlateShader::LineSegment) { // The lookup table used for splines should clamp when sampling otherwise the results are wrong PixelShader->SetTexture(RHICmdList, TextureRHI, BilinearClamp ); } else if( ShaderResource && IsValidRef( TextureRHI ) ) { FSamplerStateRHIRef SamplerState; if( DrawFlags == (ESlateBatchDrawFlag::TileU | ESlateBatchDrawFlag::TileV) ) { SamplerState = TStaticSamplerState<SF_Bilinear, AM_Wrap, AM_Wrap, AM_Wrap>::GetRHI(); } else if (DrawFlags & ESlateBatchDrawFlag::TileU) { SamplerState = TStaticSamplerState<SF_Bilinear, AM_Wrap, AM_Clamp, AM_Wrap>::GetRHI(); } else if (DrawFlags & ESlateBatchDrawFlag::TileV) { SamplerState = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Wrap, AM_Wrap>::GetRHI(); } else { SamplerState = BilinearClamp; } PixelShader->SetTexture(RHICmdList, TextureRHI, SamplerState); } else { PixelShader->SetTexture(RHICmdList, GWhiteTexture->TextureRHI, BilinearClamp); } PixelShader->SetShaderParams(RHICmdList, ShaderParams.PixelParams); PixelShader->SetDisplayGamma(RHICmdList, (DrawFlags & ESlateBatchDrawFlag::NoGamma) ? 1.0f : 1.0f/DisplayGamma); check(RenderBatch.NumIndices > 0); uint32 PrimitiveCount = RenderBatch.DrawPrimitiveType == ESlateDrawPrimitive::LineList ? RenderBatch.NumIndices / 2 : RenderBatch.NumIndices / 3; // for RHIs that can't handle VertexOffset, we need to offset the stream source each time if (!GRHISupportsBaseVertexIndex) { RHICmdList.SetStreamSource(0, VertexBuffer.VertexBufferRHI, sizeof(FSlateVertex), RenderBatch.VertexOffset * sizeof(FSlateVertex)); RHICmdList.DrawIndexedPrimitive(IndexBuffer.IndexBufferRHI, GetRHIPrimitiveType(RenderBatch.DrawPrimitiveType), 0, 0, RenderBatch.NumVertices, RenderBatch.IndexOffset, PrimitiveCount, 1); } else { RHICmdList.DrawIndexedPrimitive(IndexBuffer.IndexBufferRHI, GetRHIPrimitiveType(RenderBatch.DrawPrimitiveType), RenderBatch.VertexOffset, 0, RenderBatch.NumVertices, RenderBatch.IndexOffset, PrimitiveCount, 1); } } else if (ShaderResource && ShaderResource->GetType() == ESlateShaderResource::Material) { if (!SceneView) { SceneView = &CreateSceneView(SceneViewContext, BackBuffer, ViewProjectionMatrix); } FMaterialRenderProxy* MaterialRenderProxy = ((FSlateMaterialResource*)ShaderResource)->GetRenderProxy(); const FMaterial* Material = MaterialRenderProxy->GetMaterial(SceneView->GetFeatureLevel()); FSlateMaterialShaderPS* PixelShader = GetMaterialPixelShader( Material, ShaderType, DrawEffects ); if( PixelShader ) { RHICmdList.SetLocalBoundShaderState(RHICmdList.BuildLocalBoundShaderState( GSlateVertexDeclaration.VertexDeclarationRHI, VertexShader->GetVertexShader(), nullptr, nullptr, PixelShader->GetPixelShader(), FGeometryShaderRHIRef())); PixelShader->SetParameters(RHICmdList, *SceneView, MaterialRenderProxy, Material, 1.0f / DisplayGamma, ShaderParams.PixelParams); VertexShader->SetViewProjection( RHICmdList, ViewProjectionMatrix ); check(RenderBatch.NumIndices > 0); uint32 PrimitiveCount = RenderBatch.DrawPrimitiveType == ESlateDrawPrimitive::LineList ? RenderBatch.NumIndices / 2 : RenderBatch.NumIndices / 3; // for RHIs that can't handle VertexOffset, we need to offset the stream source each time if (!GRHISupportsBaseVertexIndex) { RHICmdList.SetStreamSource(0, VertexBuffer.VertexBufferRHI, sizeof(FSlateVertex), RenderBatch.VertexOffset * sizeof(FSlateVertex)); RHICmdList.DrawIndexedPrimitive(IndexBuffer.IndexBufferRHI, GetRHIPrimitiveType(RenderBatch.DrawPrimitiveType), 0, 0, RenderBatch.NumVertices, RenderBatch.IndexOffset, PrimitiveCount, 1); } else { RHICmdList.DrawIndexedPrimitive(IndexBuffer.IndexBufferRHI, GetRHIPrimitiveType(RenderBatch.DrawPrimitiveType), RenderBatch.VertexOffset, 0, RenderBatch.NumVertices, RenderBatch.IndexOffset, PrimitiveCount, 1); } } } } else { TSharedPtr<ICustomSlateElement, ESPMode::ThreadSafe> CustomDrawer = RenderBatch.CustomDrawer.Pin(); if (CustomDrawer.IsValid()) { // This element is custom and has no Slate geometry. Tell it to render itself now CustomDrawer->DrawRenderThread(RHICmdList, &BackBuffer.GetRenderTargetTexture()); // Something may have messed with the viewport size so set it back to the full target. RHICmdList.SetViewport( 0,0,0,BackBuffer.GetSizeXY().X, BackBuffer.GetSizeXY().Y, 0.0f ); RHICmdList.SetStreamSource(0, VertexBuffer.VertexBufferRHI, sizeof(FSlateVertex), 0); } } } CurrentBufferIndex = (CurrentBufferIndex + 1) % 2; }
void FMaterialShader::SetParameters( FRHICommandList& RHICmdList, const ShaderRHIParamRef ShaderRHI, const FMaterialRenderProxy* MaterialRenderProxy, const FMaterial& Material, const FSceneView& View, bool bDeferredPass, ESceneRenderTargetsMode::Type TextureMode) { ERHIFeatureLevel::Type FeatureLevel = View.GetFeatureLevel(); FUniformExpressionCache TempUniformExpressionCache; const FUniformExpressionCache* UniformExpressionCache = &MaterialRenderProxy->UniformExpressionCache[FeatureLevel]; SetParameters(RHICmdList, ShaderRHI, View); // If the material has cached uniform expressions for selection or hover // and that is being overridden by show flags in the editor, recache // expressions for this draw call. const bool bOverrideSelection = GIsEditor && !View.Family->EngineShowFlags.Selection && (MaterialRenderProxy->IsSelected() || MaterialRenderProxy->IsHovered()); if (!bAllowCachedUniformExpressions || !UniformExpressionCache->bUpToDate || bOverrideSelection) { FMaterialRenderContext MaterialRenderContext(MaterialRenderProxy, Material, &View); MaterialRenderProxy->EvaluateUniformExpressions(TempUniformExpressionCache, MaterialRenderContext, &RHICmdList); UniformExpressionCache = &TempUniformExpressionCache; } check(Material.GetRenderingThreadShaderMap()); check(Material.GetRenderingThreadShaderMap()->IsValidForRendering()); check(Material.GetFeatureLevel() == FeatureLevel); // Validate that the shader is being used for a material that matches the uniform expression set the shader was compiled for. const FUniformExpressionSet& MaterialUniformExpressionSet = Material.GetRenderingThreadShaderMap()->GetUniformExpressionSet(); #if NO_LOGGING == 0 const bool bUniformExpressionSetMismatch = !DebugUniformExpressionSet.Matches(MaterialUniformExpressionSet) || UniformExpressionCache->CachedUniformExpressionShaderMap != Material.GetRenderingThreadShaderMap(); if (bUniformExpressionSetMismatch) { UE_LOG( LogShaders, Fatal, TEXT("%s shader uniform expression set mismatch for material %s/%s.\n") TEXT("Shader compilation info: %s\n") TEXT("Material render proxy compilation info: %s\n") TEXT("Shader uniform expression set: %u vectors, %u scalars, %u 2D textures, %u cube textures, %u scalars/frame, %u vectors/frame, shader map %p\n") TEXT("Material uniform expression set: %u vectors, %u scalars, %u 2D textures, %u cube textures, %u scalars/frame, %u vectors/frame, shader map %p\n"), GetType()->GetName(), *MaterialRenderProxy->GetFriendlyName(), *Material.GetFriendlyName(), *DebugDescription, *Material.GetRenderingThreadShaderMap()->GetDebugDescription(), DebugUniformExpressionSet.NumVectorExpressions, DebugUniformExpressionSet.NumScalarExpressions, DebugUniformExpressionSet.Num2DTextureExpressions, DebugUniformExpressionSet.NumCubeTextureExpressions, DebugUniformExpressionSet.NumPerFrameScalarExpressions, DebugUniformExpressionSet.NumPerFrameVectorExpressions, UniformExpressionCache->CachedUniformExpressionShaderMap, MaterialUniformExpressionSet.UniformVectorExpressions.Num(), MaterialUniformExpressionSet.UniformScalarExpressions.Num(), MaterialUniformExpressionSet.Uniform2DTextureExpressions.Num(), MaterialUniformExpressionSet.UniformCubeTextureExpressions.Num(), MaterialUniformExpressionSet.PerFrameUniformScalarExpressions.Num(), MaterialUniformExpressionSet.PerFrameUniformVectorExpressions.Num(), Material.GetRenderingThreadShaderMap() ); } #endif if (UniformExpressionCache->LocalUniformBuffer.IsValid()) { // Set the material uniform buffer. SetLocalUniformBufferParameter(RHICmdList, ShaderRHI, MaterialUniformBuffer, UniformExpressionCache->LocalUniformBuffer); } else { // Set the material uniform buffer. SetUniformBufferParameter(RHICmdList, ShaderRHI, MaterialUniformBuffer, UniformExpressionCache->UniformBuffer); } { const TArray<FGuid>& ParameterCollections = UniformExpressionCache->ParameterCollections; const int32 ParameterCollectionsNum = ParameterCollections.Num(); check(ParameterCollectionUniformBuffers.Num() >= ParameterCollectionsNum); // Find each referenced parameter collection's uniform buffer in the scene and set the parameter for (int32 CollectionIndex = 0; CollectionIndex < ParameterCollectionsNum; CollectionIndex++) { FUniformBufferRHIParamRef UniformBuffer = GetParameterCollectionBuffer(ParameterCollections[CollectionIndex], View.Family->Scene); SetUniformBufferParameter(RHICmdList, ShaderRHI,ParameterCollectionUniformBuffers[CollectionIndex],UniformBuffer); } } { // Per frame material expressions const int32 NumScalarExpressions = PerFrameScalarExpressions.Num(); const int32 NumVectorExpressions = PerFrameVectorExpressions.Num(); if (NumScalarExpressions > 0 || NumVectorExpressions > 0) { FMaterialRenderContext MaterialRenderContext(MaterialRenderProxy, Material, &View); MaterialRenderContext.Time = View.Family->CurrentWorldTime; MaterialRenderContext.RealTime = View.Family->CurrentRealTime; for (int32 Index = 0; Index < NumScalarExpressions; ++Index) { auto& Parameter = PerFrameScalarExpressions[Index]; if (Parameter.IsBound()) { FLinearColor TempValue; MaterialUniformExpressionSet.PerFrameUniformScalarExpressions[Index]->GetNumberValue(MaterialRenderContext, TempValue); SetShaderValue(RHICmdList, ShaderRHI, Parameter, TempValue.R); } } for (int32 Index = 0; Index < NumVectorExpressions; ++Index) { auto& Parameter = PerFrameVectorExpressions[Index]; if (Parameter.IsBound()) { FLinearColor TempValue; MaterialUniformExpressionSet.PerFrameUniformVectorExpressions[Index]->GetNumberValue(MaterialRenderContext, TempValue); SetShaderValue(RHICmdList, ShaderRHI, Parameter, TempValue); } } // Now previous frame's expressions const int32 NumPrevScalarExpressions = PerFramePrevScalarExpressions.Num(); const int32 NumPrevVectorExpressions = PerFramePrevVectorExpressions.Num(); if (NumPrevScalarExpressions > 0 || NumPrevVectorExpressions > 0) { MaterialRenderContext.Time = View.Family->CurrentWorldTime - View.Family->DeltaWorldTime; MaterialRenderContext.RealTime = View.Family->CurrentRealTime - View.Family->DeltaWorldTime; for (int32 Index = 0; Index < NumPrevScalarExpressions; ++Index) { auto& Parameter = PerFramePrevScalarExpressions[Index]; if (Parameter.IsBound()) { FLinearColor TempValue; MaterialUniformExpressionSet.PerFramePrevUniformScalarExpressions[Index]->GetNumberValue(MaterialRenderContext, TempValue); SetShaderValue(RHICmdList, ShaderRHI, Parameter, TempValue.R); } } for (int32 Index = 0; Index < NumPrevVectorExpressions; ++Index) { auto& Parameter = PerFramePrevVectorExpressions[Index]; if (Parameter.IsBound()) { FLinearColor TempValue; MaterialUniformExpressionSet.PerFramePrevUniformVectorExpressions[Index]->GetNumberValue(MaterialRenderContext, TempValue); SetShaderValue(RHICmdList, ShaderRHI, Parameter, TempValue); } } } } } DeferredParameters.Set(RHICmdList, ShaderRHI, View, TextureMode); AtmosphericFogTextureParameters.Set(RHICmdList, ShaderRHI, View); if (FeatureLevel >= ERHIFeatureLevel::SM4) { // for copied scene color if(LightAttenuation.IsBound()) { SetTextureParameter( RHICmdList, ShaderRHI, LightAttenuation, LightAttenuationSampler, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), GSceneRenderTargets.GetLightAttenuationTexture()); } } //Use of the eye adaptation texture here is experimental and potentially dangerous as it can introduce a feedback loop. May be removed. if(EyeAdaptation.IsBound()) { FTextureRHIRef& EyeAdaptationTex = GetEyeAdaptation(View); SetTextureParameter(RHICmdList, ShaderRHI, EyeAdaptation, EyeAdaptationTex); } if (PerlinNoiseGradientTexture.IsBound() && IsValidRef(GSystemTextures.PerlinNoiseGradient)) { const FTexture2DRHIRef& Texture = (FTexture2DRHIRef&)GSystemTextures.PerlinNoiseGradient->GetRenderTargetItem().ShaderResourceTexture; // Bind the PerlinNoiseGradientTexture as a texture SetTextureParameter( RHICmdList, ShaderRHI, PerlinNoiseGradientTexture, PerlinNoiseGradientTextureSampler, TStaticSamplerState<SF_Point,AM_Wrap,AM_Wrap,AM_Wrap>::GetRHI(), Texture ); } if (PerlinNoise3DTexture.IsBound() && IsValidRef(GSystemTextures.PerlinNoise3D)) { const FTexture3DRHIRef& Texture = (FTexture3DRHIRef&)GSystemTextures.PerlinNoise3D->GetRenderTargetItem().ShaderResourceTexture; // Bind the PerlinNoise3DTexture as a texture SetTextureParameter( RHICmdList, ShaderRHI, PerlinNoise3DTexture, PerlinNoise3DTextureSampler, TStaticSamplerState<SF_Bilinear,AM_Wrap,AM_Wrap,AM_Wrap>::GetRHI(), Texture ); } GlobalDistanceFieldParameters.Set(RHICmdList, ShaderRHI, static_cast<const FViewInfo&>(View).GlobalDistanceFieldInfo.ParameterData); }
/** * Set any shader data specific to this vertex factory */ virtual void SetMesh(FRHICommandList& RHICmdList, FShader* Shader, const FVertexFactory* VertexFactory, const FSceneView& View, const FMeshBatchElement& BatchElement, uint32 DataFlags) const override { if(Shader->GetVertexShader()) { const auto FeatureLevel = View.GetFeatureLevel(); const FGPUBaseSkinVertexFactory::ShaderDataType& ShaderData = ((const FGPUBaseSkinVertexFactory*)VertexFactory)->GetShaderData(); SetShaderValue( RHICmdList, Shader->GetVertexShader(), MeshOriginParameter, ShaderData.MeshOrigin ); SetShaderValue( RHICmdList, Shader->GetVertexShader(), MeshExtensionParameter, ShaderData.MeshExtension ); if (FeatureLevel >= ERHIFeatureLevel::SM4) { if(BoneMatrices.IsBound()) { RHICmdList.SetShaderResourceViewParameter(Shader->GetVertexShader(), BoneMatrices.GetBaseIndex(), ShaderData.GetBoneBuffer().VertexBufferSRV); } } else { SetUniformBufferParameter(RHICmdList, Shader->GetVertexShader(), Shader->GetUniformBufferParameter<FBoneMatricesUniformShaderParameters>(), ShaderData.GetUniformBuffer()); } bool bLocalPerBoneMotionBlur = false; if (FeatureLevel >= ERHIFeatureLevel::SM4 && GPrevPerBoneMotionBlur.IsLocked()) { // we are in the velocity rendering pass // 0xffffffff or valid index uint32 OldBoneDataIndex = ShaderData.GetOldBoneData(View.FrameNumber); // Read old data if it was written last frame (normal data) or this frame (e.g. split screen) bLocalPerBoneMotionBlur = (OldBoneDataIndex != 0xffffffff); // we tell the shader where to pickup the data (always, even if we don't have bone data, to avoid false binding) if(PreviousBoneMatrices.IsBound()) { RHICmdList.SetShaderResourceViewParameter(Shader->GetVertexShader(), PreviousBoneMatrices.GetBaseIndex(), GPrevPerBoneMotionBlur.GetReadData()->BoneBuffer.VertexBufferSRV); } if(bLocalPerBoneMotionBlur) { uint32 BoneIndexOffsetValue[4]; BoneIndexOffsetValue[0] = OldBoneDataIndex; BoneIndexOffsetValue[1] = OldBoneDataIndex + 1; BoneIndexOffsetValue[2] = OldBoneDataIndex + 2; BoneIndexOffsetValue[3] = 0; SetShaderValue( RHICmdList, Shader->GetVertexShader(), BoneIndexOffset, BoneIndexOffsetValue ); } FScopeLock Lock(&ShaderData.OldBoneDataLock); // if we haven't copied the data yet we skip the update (e.g. split screen) if(ShaderData.IsOldBoneDataUpdateNeeded(View.FrameNumber)) { const FGPUBaseSkinVertexFactory* GPUVertexFactory = (const FGPUBaseSkinVertexFactory*)VertexFactory; // copy the bone data and tell the instance where it can pick it up next frame // append data to a buffer we bind next frame to read old matrix data for motion blur uint32 OldBoneDataStartIndex = GPrevPerBoneMotionBlur.AppendData(ShaderData.BoneMatrices.GetData(), ShaderData.BoneMatrices.Num()); GPUVertexFactory->SetOldBoneDataStartIndex(View.FrameNumber, OldBoneDataStartIndex); } } SetShaderValue(RHICmdList, Shader->GetVertexShader(), PerBoneMotionBlur, bLocalPerBoneMotionBlur); } }
void SetParameters( FRHICommandList& RHICmdList, const FSceneView& View, int32 SurfelStartIndexValue, int32 NumSurfelsToGenerateValue, const FMaterialRenderProxy* MaterialProxy, FUniformBufferRHIParamRef PrimitiveUniformBuffer, const FMatrix& Instance0Transform ) { FComputeShaderRHIParamRef ShaderRHI = GetComputeShader(); FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, View.ViewUniformBuffer, true, ESceneRenderTargetsMode::SetTextures); SetUniformBufferParameter(RHICmdList, ShaderRHI,GetUniformBufferParameter<FPrimitiveUniformShaderParameters>(),PrimitiveUniformBuffer); const FScene* Scene = (const FScene*)View.Family->Scene; FUnorderedAccessViewRHIParamRef UniformMeshUAVs[1]; UniformMeshUAVs[0] = Scene->DistanceFieldSceneData.SurfelBuffers->Surfels.UAV; RHICmdList.TransitionResources(EResourceTransitionAccess::ERWBarrier, EResourceTransitionPipeline::EComputeToCompute, UniformMeshUAVs, ARRAY_COUNT(UniformMeshUAVs)); SurfelBufferParameters.Set(RHICmdList, ShaderRHI, *Scene->DistanceFieldSceneData.SurfelBuffers, *Scene->DistanceFieldSceneData.InstancedSurfelBuffers); SetShaderValue(RHICmdList, ShaderRHI, SurfelStartIndex, SurfelStartIndexValue); SetShaderValue(RHICmdList, ShaderRHI, NumSurfelsToGenerate, NumSurfelsToGenerateValue); SetShaderValue(RHICmdList, ShaderRHI, Instance0InverseTransform, Instance0Transform.Inverse()); }
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, true, ESceneRenderTargetsMode::SetTextures); FTransform ComponentTrans = DecalProxy.ComponentTrans; // 1,1,1 requires no scale // ComponentTrans = ComponentTrans.GetScaled(GDefaultDecalSize); FMatrix WorldToComponent = ComponentTrans.ToMatrixWithScale().InverseFast(); // Set the transform from screen space to light space. if(ScreenToDecal.IsBound()) { const FMatrix ScreenToDecalValue = FMatrix( FPlane(1,0,0,0), FPlane(0,1,0,0), FPlane(0,0,View.ViewMatrices.ProjMatrix.M[2][2],1), FPlane(0,0,View.ViewMatrices.ProjMatrix.M[3][2],0) ) * View.InvViewProjectionMatrix * WorldToComponent; SetShaderValue(RHICmdList, ShaderRHI, ScreenToDecal, ScreenToDecalValue); } // Set the transform from light space to world space (only for normals) if(DecalToWorld.IsBound()) { const FMatrix DecalToWorldValue = ComponentTrans.ToMatrixNoScale(); // 1,1,1 requires no scale // DecalToWorldValue = DecalToWorldValue.GetScaled(GDefaultDecalSize); SetShaderValue(RHICmdList, ShaderRHI, DecalToWorld, DecalToWorldValue); } }