0
$\begingroup$

I used to render only when changing the positions of the lights and FPS was acceptable, but it turned out that I needed dynamic shadows for animated characters. FPS now does not rise above 58 frames per second, and judging by the indicators, the video card is idle.

 // rendering depth to render texture for point light bool lightPosChanged = false; for (int i = 0; i < NUM_POINT_LIGHTS; i++) { lightPosChanged = lightPositionsPrev[i] != m_Cameras[1 + i].GetPosition(); if (lightPosChanged) break; } if (lightPosChanged || true) { for (int i = 0; i < NUM_POINT_LIGHTS; i++) { PreparePointLightViewMatrixes(m_Cameras[i + 1].GetPosition()); //static_cast<DX11RendererAPI*>(RendererAPI::GetInstance().get())->SetCullFront(); m_PointLightDepthVertexShader->Bind(); m_PointLightDepthGeometryShader->Bind(); m_PointLightDepthPixelShader->Bind(); PointLightDepthToTextureBegin(i); RenderScene(m_Cameras[0].GetViewMatrix(), lightProjMat, m_PointLightDepthVertexShader, m_PointLightDepthPixelShader, m_PointLightDepthGeometryShader, false, nullptr, 0, false); PointLightDepthToTextureEnd(i); m_PointLightDepthVertexShader->Unbind(); m_PointLightDepthGeometryShader->Unbind(); m_PointLightDepthPixelShader->Unbind(); //static_cast<DX11RendererAPI*>(RendererAPI::GetInstance().get())->SetCullBack(); } lightPositionsPrev[0] = m_Cameras[1].GetPosition(); lightPositionsPrev[1] = m_Cameras[2].GetPosition(); lightPositionsPrev[2] = m_Cameras[3].GetPosition(); } 

I am using the geometry shader to render shadows to a cubemap:

struct Output { float4 Pos : SV_POSITION; float2 uv : TEXCOORD0; uint RTIndex : SV_RenderTargetArrayIndex; }; [maxvertexcount(18)] void GSMain(triangle Input input[3], inout TriangleStream<Output> OutStream) { for (int iFace = 0; iFace < 6; iFace++) { Output output; output.RTIndex = iFace; for (int v = 0; v < 3; v++) { output.Pos = mul(input[v].position, CubeView[iFace]); output.Pos = mul(output.Pos, CubeProj); output.uv = input[v].uv; OutStream.Append(output); } OutStream.RestartStrip(); } } ``` 
$\endgroup$
1
  • $\begingroup$ So if the light is static, you don't have to render to all cubemap faces just because a player is nearby. You can try to identify the cubemap faces that need changes and render only those $\endgroup$ Commented Feb 16 at 10:23

1 Answer 1

1
$\begingroup$

The question is fairly generic, so is this answer.

If the gpu is largely idle, and the cpu is largely idle then the bottle neck could be the geometry shader having throughput issues. The fix would be to not use the geometry shader for rendering cube maps. But there isn't much info here to go on, like the cpu usage isn't listed.

The answer to the base question is, yes there are considerable techniques to improve upon basic cube map rendering with a geometry shader.

Here are some technique improvements: Point lights in particular are easy to cull against since they are almost always a sphere. Culling geometry against that sphere and skipping draws that fail is done on the CPU usually, and is a must do. Using scissor regions when drawing clips geometry, this is particularly useful when rendering the final scene, a z component can be added to further reduce unneeded shading. To be fair scissor regions are less useful for point light shadow rendering but are performant when rendering the final scene.

Using shadow generation techniques that don't involve a fragment shader can be very performant a 200% performance uptick is plausible. Using a geometry shader can hurt performance even when there is no fragment shader. It forces single threaded throughput of every triangle and when the geometry shader is outputting 18 points per a triangle that is just a performance killer. It reduces vertex throughput, increases memory traffic, and causes pipeline stalls. Modern architectures are moving away from geometry shaders because of this type of issue. (and other reasons)

There are a number of vertex shader techniques that can be employed like shadow biasing via vertex offsets, perspective division for shadow artifacts, LOD selection (using simplified geometry usually improves performance without hurting visuals), and Vertex ID-based Instancing (which can be used to skip the geometry shader), the list goes on.

Overall I recommend moving away from geometry shaders that increase vertex count, geometry shaders are useful for culling, and modifying geometry in place but can become a bottleneck when increasing vertex count. (because geometry shaders are instance based, per a triangle, performance issues tend to persist regardless of technique)

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.