Image Alt


Custom Stereo-Rendering Gem in Lumberyard

Step by step guide how you could create generic lumberyard gem and do custom stereo rendering in Lumberyard engine.

Last version of gem you could find in Github

1. I hope you already downloaded and installed the latest version of Lumberyard. If not, you can find it here:

2. Create a new gem inside StarterGame


3. Download and install DirectX SDK . use default installation settings. We need DirectX SDK for custom stereo rendering pipeline inside Lumberyard Engine and compilation DirectX HLSH shaders

4. Our next steps will be related to Source code of StereoRendering plugin, so please download it from Github

5. Let’s take a look into Gem configuration files first. First, start from wscript inside StereoRendering/Code. IMPORTANT: here you need to provide a path to DirectX SDK lib and include, as our gem code is the default path to SDK, which was set after installation of DirectX SDK

[code language=”python”]
def build(bld):

# Compiler Specific
win_cxxflags = [

win_lib = [ ‘d3d11’,

includes = [
‘C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include’

# General
file_list = [‘sr.waf_files’],

win_stlibpath = [‘C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64’],

6. Next lets look at sr.waf_files inside StereoRendering/Code. This file is responsible for the configuration for compiling C++ for your gem. This file should contain all C++ source and header files which we need to compile

[code language=”js”]
"none": {
"Source": [
"auto": {
"Include": [
"Source": [
"Implementation": [
"Rendering": [

7. Ok, lets try to understand all c++ source files


  • SRGem.ccp – this is the main gem plugin, where we defined all system components and console variables, it is the initial point for gem execution
  • SRDevice.cpp – this is the component which is responsible for running lumberyard in stereo mode, creation stereo left and right render targets, provide dynamic variables for rendering (for projection matrices, the position of the user in space, etc)
  • SRRendering.cpp – this is a Class for custom stereo rendering, it is content logic from DirectX stereo rendering pipeline, access to custom shaders. You could include your own custom shaders here and it will draw to back buffer at last moment before frame will be presented to screen.
  • If you go to StereoRendering /Assets/Shaders you could find stereorendering.cfx Shader which is responsible for Stereo Rendering. That is the place where you could write shader logic.

[code language=”cpp”]
Texture2D LeftTexture : register(t0); // Texture from framebuffer
SamplerState LeftTextureSamplerState : register(s0);

Texture2D RightTexture : register(t1); // Texture from framebuffer
SamplerState RightTextureSamplerState : register(s1);

cbuffer cbPerObject
// 1rd Group of 16 bytes
int ScreenSize; // 8 bytes 4 * 2
float pad1; // 4 bytes
float pad2; // 4 bytes

struct VS_OUTPUT
float4 Pos : SV_POSITION;
float2 TexCoord : TEXCOORD0;

VS_OUTPUT VS(float4 inPos : POSITION, float2 inTexCoord : TEXCOORD)
VS_OUTPUT output;

output.Pos = inPos;
output.TexCoord = inTexCoord;

return output;

float4 PS(VS_OUTPUT input) : SV_TARGET
if (input.Pos.x < ScreenSize.x / 2)
return LeftTexture.Sample(LeftTextureSamplerState, input.TexCoord);
return RightTexture.Sample(RightTextureSamplerState, input.TexCoord);


Profiling stereo rendering
If you really want to understand how rendering is done you need to start profiling in SRDevice.cpp, just go to SRDevice::SubmitFrame() function, this the place where you could start debugging

[code language=”cpp”]
void SRDevice::SubmitFrame(const EyeTarget & left, const EyeTarget & right)
if (m_SRRenderer.get() != nullptr)

DrawScene() function contains all logic for DirectX 11 rendering pipeline

[code language=”cpp”]
void SRRenderer::DrawScene()
//Set the Input Layout

//Set Primitive Topology

//Set the spheres index buffer
d3d11DevCon->IASetIndexBuffer(squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

//Set the spheres vertex buffer
UINT stride = sizeof(Vertex);
UINT offset = 0;
d3d11DevCon->IASetVertexBuffers(0, 1, &squareVertBuffer, &stride, &offset);

//Set the new VS and PS shaders
d3d11DevCon->VSSetShader(VS, 0, 0);
d3d11DevCon->PSSetShader(PS, 0, 0);

// Set texture resources
d3d11DevCon->PSSetShaderResources(0, 1, &LeftTextureRV);
d3d11DevCon->PSSetSamplers(0, 1, &TexSamplerState);
d3d11DevCon->PSSetShaderResources(1, 1, &RightTextureRV);
d3d11DevCon->PSSetSamplers(1, 1, &TexSamplerState);

// Update constant buffer
d3d11DevCon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0);
d3d11DevCon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer);
d3d11DevCon->PSSetConstantBuffers(0, 1, &cbPerObjectBuffer);

//Draw the triangle
d3d11DevCon->DrawIndexed(6, 0, 0);

You can look deeper into the rendering pipeline with RenderDoc GPU debugger

%d bloggers like this: