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);
151 auto& blend = blendStates[size_t(BlendMode::DestinationAlpha_InverseDestinationAlpha)];
152 blend.color.enabled =
true;
153 blend.color.sourceBlend = BlendState::Blend::DestinationAlpha;
154 blend.color.destinationBlend = BlendState::Blend::InverseDestinationAlpha;
155 blend.color.operation = BlendState::BlendOperation::Add;
156 blend.alpha = blend.color;
157 blend.handle = renderTargets->loadBlendState(blend.color, blend.alpha);
160 setupDepthStates(device);
163 SamplerState states[] = {
170 for (
size_t i = 0; i < 4; ++i) {
171 commonSamplerStates[i] = textures->loadSamplerState(states[i]);
174 SamplerState shadowSamplerState{};
175 switch (device->getType()) {
181 shadowSamplerState.comparisonFunction = reverseDepth ? SamplerState::GreaterEqual : SamplerState::LessEqual;
188 shadowSamplerState.comparisonFunction = reverseDepth ? SamplerState::GreaterEqual : SamplerState::LessEqual;
190 for (
size_t i = 0; i < 4; i++) {
191 shadowSamplerState.borderColor[i] = reverseDepth ? 0.f : 1.f;
195 shadowSampler = textures->loadSamplerState(shadowSamplerState);
197 IBuffers * buffers = device->getBuffers();
199 const glm::vec4 fst[] =
201 {-1.0, -1.0, 0.0, 1.f},
202 { 3.0, -1.0, 0.0, 1.f},
203 {-1.0, 3.0, 0.0, 1.f},
206 fullScreenTriangle = buffers->loadVertexBuffer(fst,
sizeof(fst) /
sizeof(fst[0]), VertexFormats::Pos4f);
209void Cogs::Core::RenderStates::setupDepthStates(IGraphicsDevice* device) {
210 auto renderTargets = device->getRenderTargets();
213 defaultDepthStencilStateHandle = renderTargets->loadDepthStencilState(defaultState);
218 noWriteDepthStencilStateHandle = renderTargets->loadDepthStencilState(depthState);
222 noTestDepthStencilStateHandle = renderTargets->loadDepthStencilState(noTestDepthState);
225 noDepthStencilStateHandle = renderTargets->loadDepthStencilState(noDepthState);
230 leqDepthStencilStateHandle = renderTargets->loadDepthStencilState(leqState);
232 for (
int depthMode = 0; depthMode < 4; depthMode++) {
233 for (
int depthFunc = 0; depthFunc < 5; depthFunc++) {
236 case DepthFunc::Less:
239 case DepthFunc::Always:
242 case DepthFunc::LessOrEqual:
245 case DepthFunc::NotEqual:
248 case DepthFunc::Equal:
251 case DepthFunc::Count:
256 state.depthFunction = depthFunction;
261 state = {
true,
false, depthFunction };
267 state = {
false,
false, depthFunction };
269 case DepthMode::Count:
273 commonDepthStates[depthFunc * (int)DepthMode::Count + depthMode] = renderTargets->loadDepthStencilState(state);
278void Cogs::Core::RenderStates::cleanup()
280 for (
auto & d : depthStencilStates) {
281 device->getRenderTargets()->releaseDepthStencilState(d.second);
284 for (
auto & r : rasterizerStates) {
285 device->getRenderTargets()->releaseRasterizerState(r.second.handle);
288 for (
auto & s : samplerStates) {
289 device->getTextures()->releaseSamplerState(s.second);
292 depthStencilStates.clear();
293 rasterizerStates.clear();
294 samplerStates.clear();
299 size_t getDefaultRenderPassOptionsHash() {
301 options.updateHash();
311 bool counterClockWise)
314 static const size_t defaultRenderPassOptionsHash = getDefaultRenderPassOptionsHash();
315 if (wireFrame || passOptions.
hash != defaultRenderPassOptionsHash) {
318 rasterizerState.wireFrame = wireFrame;
319 rasterizerState.cullMode = cullMode;
320 rasterizerState.frontCounterClockwise = counterClockWise;
321 rasterizerState.noDepthClip = passOptions.getFlag(RenderPassOptions::Flags::NoDepthClip);
322 rasterizerState.depthBias = passOptions.depthBias;
323 rasterizerState.slopeScaledDepthBias = passOptions.depthSlopedBias;
324 rasterizerState.depthBiasClamp = passOptions.depthBiasClamp;
325 rasterizerState.scissor = passOptions.getFlag(RenderPassOptions::Flags::ScissorTest);
327 return getRasterizerState(rasterizerState);
329 return (uint16_t)(cullMode * 2 + counterClockWise);
333uint16_t Cogs::Core::RenderStates::getRasterizerState(
const RasterizerState & rs_a)
335 RasterizerState rs = rs_a;
337 rs.depthBias = -rs.depthBias;
338 rs.slopeScaledDepthBias = -rs.slopeScaledDepthBias;
339 rs.depthBiasClamp = -rs.depthBiasClamp;
341 auto it = rasterizerStates.find(rs);
343 if (it == rasterizerStates.end()) {
344 LOG_TRACE(logger,
"Created rasterizer state %d.",
int(rasterizerStates.size()));
346 auto rsh = device->getRenderTargets()->loadRasterizerState(rs);
348 auto index =
static_cast<uint16_t
>(rasterizerStateHandles.size());
349 rasterizerStateHandles.emplace_back(rsh);
351 rasterizerStates[rs] = { index, rsh };
355 return it->second.index;
361 DepthStencilState ds = ds_a;
369 auto it = depthStencilStates.find(ds);
371 if (it == depthStencilStates.end()) {
372 LOG_TRACE(logger,
"Created depth stencil state %d.",
int(rasterizerStates.size()));
374 auto dsh = device->getRenderTargets()->loadDepthStencilState(ds);
376 depthStencilStates[ds] = dsh;
386 auto it = samplerStates.find(ss);
388 if (it == samplerStates.end()) {
389 LOG_TRACE(logger,
"Created sampler state %d.",
int(samplerStates.size()));
391 auto ssh = device->getTextures()->loadSamplerState(ss);
393 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.
@ WebGPU
Graphics device using the WebGPU API Backend.
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.