Skip to content

Instantly share code, notes, and snippets.

@ReanGD
Created February 22, 2020 23:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ReanGD/fa8a92d2a36c14e60e8790e353f02572 to your computer and use it in GitHub Desktop.
Save ReanGD/fa8a92d2a36c14e60e8790e353f02572 to your computer and use it in GitHub Desktop.
Problem
cbuffer Colors
{
float4 g_Color;
};
struct PSInput
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
};
struct PSOutput
{
float4 Color : SV_TARGET;
};
// Note that if separate shader objects are not supported (this is only the case for old GLES3.0 devices), vertex
// shader output variable name must match exactly the name of the pixel shader input variable.
// If the variable has structure type (like in this example), the structure declarations must also be indentical.
void main(in PSInput PSIn,
out PSOutput PSOut)
{
PSOut.Color = g_Color;
}
/*
* Copyright 2019-2020 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* In no event and under no legal theory, whether in tort (including negligence),
* contract, or otherwise, unless required by applicable law (such as deliberate
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
* liable for any damages, including any direct, indirect, special, incidental,
* or consequential damages of any character arising as a result of this License or
* out of the use or inability to use the software (including but not limited to damages
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
* all other commercial damages or losses), even if such Contributor has been advised
* of the possibility of such damages.
*/
#include "Tutorial02_Cube.hpp"
#include "MapHelper.hpp"
#include "GraphicsUtilities.h"
namespace Diligent
{
SampleBase* CreateSample()
{
return new Tutorial02_Cube();
}
void Tutorial02_Cube::CreatePipelineState()
{
// Pipeline state object encompasses configuration of all GPU stages
PipelineStateDesc PSODesc;
// Pipeline state name is used by the engine to report issues.
// It is always a good idea to give objects descriptive names.
PSODesc.Name = "Cube PSO";
// This is a graphics pipeline
PSODesc.IsComputePipeline = false;
// clang-format off
// This tutorial will render to a single render target
PSODesc.GraphicsPipeline.NumRenderTargets = 1;
// Set render target format which is the format of the swap chain's color buffer
PSODesc.GraphicsPipeline.RTVFormats[0] = m_pSwapChain->GetDesc().ColorBufferFormat;
// Set depth buffer format which is the format of the swap chain's back buffer
PSODesc.GraphicsPipeline.DSVFormat = m_pSwapChain->GetDesc().DepthBufferFormat;
// Primitive topology defines what kind of primitives will be rendered by this pipeline state
PSODesc.GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
// Cull back faces
PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_BACK;
// Enable depth testing
PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = True;
// clang-format on
ShaderCreateInfo ShaderCI;
// Tell the system that the shader source code is in HLSL.
// For OpenGL, the engine will convert this into GLSL under the hood.
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
// OpenGL backend requires emulated combined HLSL texture samplers (g_Texture + g_Texture_sampler combination)
ShaderCI.UseCombinedTextureSamplers = true;
// In this tutorial, we will load shaders from file. To be able to do that,
// we need to create a shader source stream factory
RefCntAutoPtr<IShaderSourceInputStreamFactory> pShaderSourceFactory;
m_pEngineFactory->CreateDefaultShaderSourceStreamFactory(nullptr, &pShaderSourceFactory);
ShaderCI.pShaderSourceStreamFactory = pShaderSourceFactory;
// Create a vertex shader
RefCntAutoPtr<IShader> pVS;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_VERTEX;
ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Cube VS";
ShaderCI.FilePath = "cube.vsh";
m_pDevice->CreateShader(ShaderCI, &pVS);
// Create dynamic uniform buffer that will store our transformation matrix
// Dynamic buffers can be frequently updated by the CPU
BufferDesc CBDesc;
CBDesc.Name = "VS constants CB";
CBDesc.uiSizeInBytes = sizeof(float4x4);
CBDesc.Usage = USAGE_DYNAMIC;
CBDesc.BindFlags = BIND_UNIFORM_BUFFER;
CBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
m_pDevice->CreateBuffer(CBDesc, nullptr, &m_VSConstants);
CBDesc.Name = "VS constants PB";
CBDesc.uiSizeInBytes = sizeof(float4);
CBDesc.Usage = USAGE_DYNAMIC;
CBDesc.BindFlags = BIND_UNIFORM_BUFFER;
CBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
m_pDevice->CreateBuffer(CBDesc, nullptr, &m_PSConstants);
}
// Create a pixel shader
RefCntAutoPtr<IShader> pPS;
{
ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL;
ShaderCI.EntryPoint = "main";
ShaderCI.Desc.Name = "Cube PS";
ShaderCI.FilePath = "cube.psh";
m_pDevice->CreateShader(ShaderCI, &pPS);
}
// clang-format off
// Define vertex shader input layout
LayoutElement LayoutElems[] =
{
// Attribute 0 - vertex position
LayoutElement{0, 0, 3, VT_FLOAT32, False},
// Attribute 1 - vertex color
LayoutElement{1, 0, 4, VT_FLOAT32, False}
};
// clang-format on
PSODesc.GraphicsPipeline.InputLayout.LayoutElements = LayoutElems;
PSODesc.GraphicsPipeline.InputLayout.NumElements = _countof(LayoutElems);
PSODesc.GraphicsPipeline.pVS = pVS;
PSODesc.GraphicsPipeline.pPS = pPS;
// Define variable type that will be used by default
// PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC;
PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;
m_pDevice->CreatePipelineState(PSODesc, &m_pPSO);
// Since we did not explcitly specify the type for 'Constants' variable, default
// type (SHADER_RESOURCE_VARIABLE_TYPE_STATIC) will be used. Static variables never
// change and are bound directly through the pipeline state object.
// m_pPSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "Constants")->Set(m_VSConstants);
// Create a shader resource binding object and bind all static resources in it
m_pPSO->CreateShaderResourceBinding(&m_pSRB, true);
m_pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "Constants")->Set(m_VSConstants);
m_pSRB->GetVariableByName(SHADER_TYPE_PIXEL, "Colors")->Set(m_PSConstants);
}
void Tutorial02_Cube::CreateVertexBuffer()
{
// Layout of this structure matches the one we defined in the pipeline state
struct Vertex
{
float3 pos;
float4 color;
};
// Cube vertices
// (-1,+1,+1)________________(+1,+1,+1)
// /| /|
// / | / |
// / | / |
// / | / |
//(-1,-1,+1) /____|__________/(+1,-1,+1)
// | |__________|____|
// | /(-1,+1,-1) | /(+1,+1,-1)
// | / | /
// | / | /
// |/ | /
// /_______________|/
// (-1,-1,-1) (+1,-1,-1)
//
// clang-format off
Vertex CubeVerts[8] =
{
{float3(-1,-1,-1), float4(1,0,0,1)},
{float3(-1,+1,-1), float4(0,1,0,1)},
{float3(+1,+1,-1), float4(0,0,1,1)},
{float3(+1,-1,-1), float4(1,1,1,1)},
{float3(-1,-1,+1), float4(1,1,0,1)},
{float3(-1,+1,+1), float4(0,1,1,1)},
{float3(+1,+1,+1), float4(1,0,1,1)},
{float3(+1,-1,+1), float4(0.2f,0.2f,0.2f,1)},
};
// clang-format on
// Create a vertex buffer that stores cube vertices
BufferDesc VertBuffDesc;
VertBuffDesc.Name = "Cube vertex buffer";
VertBuffDesc.Usage = USAGE_STATIC;
VertBuffDesc.BindFlags = BIND_VERTEX_BUFFER;
VertBuffDesc.uiSizeInBytes = sizeof(CubeVerts);
BufferData VBData;
VBData.pData = CubeVerts;
VBData.DataSize = sizeof(CubeVerts);
m_pDevice->CreateBuffer(VertBuffDesc, &VBData, &m_CubeVertexBuffer);
}
void Tutorial02_Cube::CreateIndexBuffer()
{
// clang-format off
Uint32 Indices[] =
{
2,0,1, 2,3,0,
4,6,5, 4,7,6,
0,7,4, 0,3,7,
1,0,4, 1,4,5,
1,5,2, 5,6,2,
3,6,7, 3,2,6
};
// clang-format on
BufferDesc IndBuffDesc;
IndBuffDesc.Name = "Cube index buffer";
IndBuffDesc.Usage = USAGE_STATIC;
IndBuffDesc.BindFlags = BIND_INDEX_BUFFER;
IndBuffDesc.uiSizeInBytes = sizeof(Indices);
BufferData IBData;
IBData.pData = Indices;
IBData.DataSize = sizeof(Indices);
m_pDevice->CreateBuffer(IndBuffDesc, &IBData, &m_CubeIndexBuffer);
}
void Tutorial02_Cube::Initialize(IEngineFactory* pEngineFactory,
IRenderDevice* pDevice,
IDeviceContext** ppContexts,
Uint32 NumDeferredCtx,
ISwapChain* pSwapChain)
{
SampleBase::Initialize(pEngineFactory, pDevice, ppContexts, NumDeferredCtx, pSwapChain);
CreatePipelineState();
CreateVertexBuffer();
CreateIndexBuffer();
}
// Render a frame
void Tutorial02_Cube::Render()
{
auto* pRTV = m_pSwapChain->GetCurrentBackBufferRTV();
auto* pDSV = m_pSwapChain->GetDepthBufferDSV();
// Clear the back buffer
const float ClearColor[] = {0.350f, 0.350f, 0.350f, 1.0f};
m_pImmediateContext->ClearRenderTarget(pRTV, ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
m_pImmediateContext->ClearDepthStencil(pDSV, CLEAR_DEPTH_FLAG, 1.f, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
static bool isFirst = true;
if (isFirst) {
isFirst = false;
// Map the buffer and write current world-view-projection matrix
MapHelper<float4> CBConstants(m_pImmediateContext, m_PSConstants, MAP_WRITE, MAP_FLAG_DISCARD);
*CBConstants = float4(1.f, 0, 0, 1.f);
}
{
// Map the buffer and write current world-view-projection matrix
MapHelper<float4x4> CBConstants(m_pImmediateContext, m_VSConstants, MAP_WRITE, MAP_FLAG_DISCARD);
*CBConstants = m_WorldViewProjMatrix.Transpose();
}
// Bind vertex and index buffers
Uint32 offset = 0;
IBuffer* pBuffs[] = {m_CubeVertexBuffer};
m_pImmediateContext->SetVertexBuffers(0, 1, pBuffs, &offset, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, SET_VERTEX_BUFFERS_FLAG_RESET);
m_pImmediateContext->SetIndexBuffer(m_CubeIndexBuffer, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
// Set the pipeline state
m_pImmediateContext->SetPipelineState(m_pPSO);
// Commit shader resources. RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode
// makes sure that resources are transitioned to required states.
m_pImmediateContext->CommitShaderResources(m_pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
DrawIndexedAttribs DrawAttrs; // This is an indexed draw call
DrawAttrs.IndexType = VT_UINT32; // Index type
DrawAttrs.NumIndices = 36;
// Verify the state of vertex and index buffers
DrawAttrs.Flags = DRAW_FLAG_VERIFY_ALL;
m_pImmediateContext->DrawIndexed(DrawAttrs);
}
void Tutorial02_Cube::Update(double CurrTime, double ElapsedTime)
{
SampleBase::Update(CurrTime, ElapsedTime);
const bool IsGL = m_pDevice->GetDeviceCaps().IsGLDevice();
// Set cube world view matrix
float4x4 CubeWorldView = float4x4::RotationY(static_cast<float>(CurrTime) * 1.0f) * float4x4::RotationX(-PI_F * 0.1f) *
float4x4::Translation(0.f, 0.0f, 5.0f);
float NearPlane = 0.1f;
float FarPlane = 100.f;
float aspectRatio = static_cast<float>(m_pSwapChain->GetDesc().Width) / static_cast<float>(m_pSwapChain->GetDesc().Height);
// Projection matrix differs between DX and OpenGL
auto Proj = float4x4::Projection(PI_F / 4.f, aspectRatio, NearPlane, FarPlane, IsGL);
// Compute world-view-projection matrix
m_WorldViewProjMatrix = CubeWorldView * Proj;
}
} // namespace Diligent
/*
* Copyright 2019-2020 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* In no event and under no legal theory, whether in tort (including negligence),
* contract, or otherwise, unless required by applicable law (such as deliberate
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
* liable for any damages, including any direct, indirect, special, incidental,
* or consequential damages of any character arising as a result of this License or
* out of the use or inability to use the software (including but not limited to damages
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
* all other commercial damages or losses), even if such Contributor has been advised
* of the possibility of such damages.
*/
#pragma once
#include "SampleBase.hpp"
#include "BasicMath.hpp"
namespace Diligent
{
class Tutorial02_Cube final : public SampleBase
{
public:
virtual void Initialize(IEngineFactory* pEngineFactory,
IRenderDevice* pDevice,
IDeviceContext** ppContexts,
Uint32 NumDeferredCtx,
ISwapChain* pSwapChain) override final;
virtual void Render() override final;
virtual void Update(double CurrTime, double ElapsedTime) override final;
virtual const Char* GetSampleName() const override final { return "Tutorial02: Cube"; }
private:
void CreatePipelineState();
void CreateVertexBuffer();
void CreateIndexBuffer();
RefCntAutoPtr<IPipelineState> m_pPSO;
RefCntAutoPtr<IShaderResourceBinding> m_pSRB;
RefCntAutoPtr<IBuffer> m_CubeVertexBuffer;
RefCntAutoPtr<IBuffer> m_CubeIndexBuffer;
RefCntAutoPtr<IBuffer> m_VSConstants;
RefCntAutoPtr<IBuffer> m_PSConstants;
float4x4 m_WorldViewProjMatrix;
};
} // namespace Diligent
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment