1#include "RenderStates.h"
5#include "Foundation/Logging/Logger.h"
7#include "Rendering/IGraphicsDevice.h"
8#include "Rendering/IRenderTargets.h"
9#include "Rendering/ITextures.h"
10#include "Rendering/IBuffers.h"
12#include "Resources/MaterialOptions.h"
13#include "Systems/Core/CameraSystem.h"
14#include "Resources/VertexFormats.h"
21void Cogs::Core::RenderStates::initialize(IGraphicsDevice * device)
23 this->device = device;
24 auto renderTargets = device->getRenderTargets();
25 auto textures = device->getTextures();
29 rs.frontCounterClockwise =
false;
30 rs.noDepthClip =
true;
31 getRasterizerState(rs);
34 rs.frontCounterClockwise =
true;
35 rs.noDepthClip =
true;
36 getRasterizerState(rs);
39 rs.frontCounterClockwise =
false;
40 rs.noDepthClip =
true;
41 getRasterizerState(rs);
44 rs.frontCounterClockwise =
true;
45 rs.noDepthClip =
true;
46 getRasterizerState(rs);
49 rs.frontCounterClockwise =
false;
50 rs.noDepthClip =
true;
51 getRasterizerState(rs);
54 rs.frontCounterClockwise =
true;
55 rs.noDepthClip =
true;
56 getRasterizerState(rs);
59 rs.noDepthClip =
true;
60 defaultRasterizerStateHandle = device->getRenderTargets()->loadRasterizerState(rs);
61 rs.frontCounterClockwise =
true;
62 defaultCCWasterizerStateHandle = device->getRenderTargets()->loadRasterizerState(rs);
66 blend.color.enabled =
true;
67 blend.color.sourceBlend = BlendState::Blend::SourceAlpha;
68 blend.color.destinationBlend = BlendState::Blend::InverseSourceAlpha;
69 blend.color.operation = BlendState::BlendOperation::Add;
70 blend.alpha.enabled =
true;
71 blend.alpha.sourceBlend = BlendState::Blend::One;
72 blend.alpha.destinationBlend = BlendState::Blend::InverseSourceAlpha;
73 blend.alpha.operation = BlendState::BlendOperation::Add;
74 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha);
79 blend.color.enabled =
true;
80 blend.color.sourceBlend = BlendState::Blend::SourceAlpha;
81 blend.color.destinationBlend = BlendState::Blend::One;
82 blend.color.operation = BlendState::BlendOperation::Add;
83 blend.alpha.enabled =
true;
84 blend.alpha.sourceBlend = BlendState::Blend::One;
85 blend.alpha.destinationBlend = BlendState::Blend::One;
86 blend.alpha.operation = BlendState::BlendOperation::Add;
87 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha);
92 blend.color.enabled =
true;
93 blend.color.sourceBlend = BlendState::Blend::One;
94 blend.color.destinationBlend = BlendState::Blend::InverseSourceAlpha;
95 blend.color.operation = BlendState::BlendOperation::Add;
96 blend.alpha.enabled =
true;
97 blend.alpha.sourceBlend = BlendState::Blend::One;
98 blend.alpha.destinationBlend = BlendState::Blend::InverseSourceAlpha;
99 blend.alpha.operation = BlendState::BlendOperation::Add;
100 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha);
105 blend.color.enabled =
false;
106 blend.alpha.enabled =
false;
107 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha, Cogs::BlendFlags::AlphaToCoverage);
112 blend.color.enabled =
false;
113 blend.alpha.enabled =
false;
114 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha);
119 blend.color.enabled =
true;
120 blend.color.sourceBlend = BlendState::Blend::Zero;
121 blend.color.destinationBlend = BlendState::Blend::One;
122 blend.color.operation = BlendState::BlendOperation::Add;
123 blend.alpha = blend.color;
124 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha);
128 auto& blend = blendStates[size_t(BlendMode::One_One_Zero_InverseSourceAlpha)];
129 blend.color.enabled =
true;
130 blend.color.sourceBlend = BlendState::Blend::One;
131 blend.color.destinationBlend = BlendState::Blend::One;
132 blend.color.operation = BlendState::BlendOperation::Add;
133 blend.alpha.enabled =
true;
134 blend.alpha.sourceBlend = BlendState::Blend::Zero;
135 blend.alpha.destinationBlend = BlendState::Blend::InverseSourceAlpha;
136 blend.alpha.operation = BlendState::BlendOperation::Add;
137 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha);
141 auto& blend = blendStates[size_t(BlendMode::InverseSourceAlpha_SourceAlpha)];
142 blend.color.enabled =
true;
143 blend.color.sourceBlend = BlendState::Blend::InverseSourceAlpha;
144 blend.color.destinationBlend = BlendState::Blend::SourceAlpha;
145 blend.color.operation = BlendState::BlendOperation::Add;
146 blend.alpha = blend.color;
147 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha);
150 setupDepthStates(device);
153 SamplerState states[] = {
160 for (
size_t i = 0; i < 4; ++i) {
161 commonSamplerStates[i] = textures->loadSamplerState(states[i]);
164 SamplerState shadowSamplerState{};
165 switch (device->getType()) {
170 shadowSamplerState.comparisonFunction = reverseDepth ? SamplerState::GreaterEqual : SamplerState::LessEqual;
177 shadowSamplerState.comparisonFunction = reverseDepth ? SamplerState::GreaterEqual : SamplerState::LessEqual;
179 for (
size_t i = 0; i < 4; i++) {
180 shadowSamplerState.borderColor[i] = reverseDepth ? 0.f : 1.f;
184 shadowSampler = textures->loadSamplerState(shadowSamplerState);
186 IBuffers * buffers = device->getBuffers();
188 const glm::vec4 fst[] =
190 {-1.0, -1.0, 0.0, 1.f},
191 { 3.0, -1.0, 0.0, 1.f},
192 {-1.0, 3.0, 0.0, 1.f},
195 fullScreenTriangle = buffers->loadVertexBuffer(fst,
sizeof(fst) /
sizeof(fst[0]), VertexFormats::Pos4f);
198void Cogs::Core::RenderStates::setupDepthStates(IGraphicsDevice* device) {
199 auto renderTargets = device->getRenderTargets();
202 defaultDepthStencilStateHandle = renderTargets->loadDepthStencilState(defaultState);
207 noWriteDepthStencilStateHandle = renderTargets->loadDepthStencilState(depthState);
211 noTestDepthStencilStateHandle = renderTargets->loadDepthStencilState(noTestDepthState);
214 noDepthStencilStateHandle = renderTargets->loadDepthStencilState(noDepthState);
217 for (
int depthMode = 0; depthMode < 4; depthMode++) {
218 for (
int depthFunc = 0; depthFunc < 5; depthFunc++) {
221 case DepthFunc::Less:
224 case DepthFunc::Always:
227 case DepthFunc::LessOrEqual:
230 case DepthFunc::NotEqual:
233 case DepthFunc::Equal:
236 case DepthFunc::Count:
241 state.depthFunction = depthFunction;
246 state = {
true,
false, depthFunction };
252 state = {
false,
false, depthFunction };
254 case DepthMode::Count:
258 commonDepthStates[depthFunc * (int)DepthMode::Count + depthMode] = renderTargets->loadDepthStencilState(state);
263void Cogs::Core::RenderStates::cleanup()
265 for (
auto & d : depthStencilStates) {
266 device->getRenderTargets()->releaseDepthStencilState(d.second);
269 for (
auto & r : rasterizerStates) {
270 device->getRenderTargets()->releaseRasterizerState(r.second.handle);
273 for (
auto & s : samplerStates) {
274 device->getTextures()->releaseSamplerState(s.second);
277 depthStencilStates.clear();
278 rasterizerStates.clear();
279 samplerStates.clear();
284 size_t getDefaultRenderPassOptionsHash() {
286 options.updateHash();
296 bool counterClockWise)
299 static const size_t defaultRenderPassOptionsHash = getDefaultRenderPassOptionsHash();
300 if (wireFrame || passOptions.
hash != defaultRenderPassOptionsHash) {
303 rasterizerState.wireFrame = wireFrame;
304 rasterizerState.cullMode = cullMode;
305 rasterizerState.frontCounterClockwise = counterClockWise;
306 rasterizerState.noDepthClip = passOptions.getFlag(RenderPassOptions::Flags::NoDepthClip);
307 rasterizerState.depthBias = passOptions.depthBias;
308 rasterizerState.slopeScaledDepthBias = passOptions.depthSlopedBias;
309 rasterizerState.depthBiasClamp = passOptions.depthBiasClamp;
310 rasterizerState.scissor = passOptions.getFlag(RenderPassOptions::Flags::ScissorTest);
312 return getRasterizerState(rasterizerState);
314 return (uint16_t)(cullMode * 2 + counterClockWise);
318uint16_t Cogs::Core::RenderStates::getRasterizerState(
const RasterizerState & rs_a)
320 RasterizerState rs = rs_a;
322 rs.depthBias = -rs.depthBias;
323 rs.slopeScaledDepthBias = -rs.slopeScaledDepthBias;
324 rs.depthBiasClamp = -rs.depthBiasClamp;
326 auto it = rasterizerStates.find(rs);
328 if (it == rasterizerStates.end()) {
329 LOG_TRACE(logger,
"Created rasterizer state %d.",
int(rasterizerStates.size()));
331 auto rsh = device->getRenderTargets()->loadRasterizerState(rs);
333 auto index =
static_cast<uint16_t
>(rasterizerStateHandles.size());
334 rasterizerStateHandles.emplace_back(rsh);
336 rasterizerStates[rs] = { index, rsh };
340 return it->second.index;
346 DepthStencilState ds = ds_a;
354 auto it = depthStencilStates.find(ds);
356 if (it == depthStencilStates.end()) {
357 LOG_TRACE(logger,
"Created depth stencil state %d.",
int(rasterizerStates.size()));
359 auto dsh = device->getRenderTargets()->loadDepthStencilState(ds);
361 depthStencilStates[ds] = dsh;
371 auto it = samplerStates.find(ss);
373 if (it == samplerStates.end()) {
374 LOG_TRACE(logger,
"Created sampler state %d.",
int(samplerStates.size()));
376 auto ssh = device->getTextures()->loadSamplerState(ss);
378 samplerStates[ss] = ssh;
Log implementation class.
@ Blend
Render with regular alpha blending.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
@ AlphaToCoverage
Interpret alpha value as a coverage mask.
@ Zero
Disable all color writes.
@ Add
Render with additive blending.
DepthMode
Defines common depth stencil modes.
@ NoWrite
Depth test enabled, write disabled.
@ Default
Default, depth test & write enabled.
@ AlwaysWrite
Depth write enabled, test mode "Always". Deprecated.
@ Disabled
Depth test/write disabled.
DepthFunc
Defines common depth functions.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
DepthFunction
Depth functions to apply when determining object visibility based on its depth test.
@ GreaterOrEqual
Greater or equal depth.
@ NotEqual
Depth not equal evaluates to true.
@ Always
Always evaluates to true.
@ LessOrEqual
Less or equal depth.
static DepthStencilState DefaultState()
Constructs a depth stencil state object initialized with the default values.
static RasterizerState DefaultState()
Constructs a rasterizer state initialized with the default values.
CullMode
Culling modes for triangle rasterization.
@ None
Do not perform any face culling.
@ Back
Cull back facing primitives.
@ Front
Cull front facing primitives.
static SamplerState & DefaultState()
Constructs a sampler state initialized with the default values.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
@ Border
Texture color is set to the border color when outside [0, 1] range.
@ Wrap
Texture coordinates automatically wrap around to [0, 1] range.
@ ComparisonMinMagMipLinear
Comparison filter for depth sample comparisons using linear interpolation sampling.
@ MinMagMipPoint
Point sampling for both minification and magnification.
@ MinMagMipLinear
Linear sampling for both minification and magnification.