|
1 | | -// Copyright (C) 2022-2025 - DevSH Graphics Programming Sp. z O.O. |
| 1 | +// Copyright (C) 2022-2025 - DevSH Graphics Programming Sp. z O.O. |
2 | 2 | // This file is part of the "Nabla Engine". |
3 | 3 | // For conditions of distribution and use, see copyright notice in nabla.h |
4 | 4 | #include "nbl/asset/material_compiler3/CFrontendIR.h" |
@@ -32,6 +32,11 @@ bool CFrontendIR::CBeer::invalid(const SInvalidCheckArgs& args) const |
32 | 32 | args.logger.log("Perpendicular Transparency node of correct type must be attached, but is %u of type %s",ELL_ERROR,perpTransmittance,args.pool->getTypeName(perpTransmittance).data()); |
33 | 33 | return true; |
34 | 34 | } |
| 35 | + if (const auto* const thick=args.pool->getObjectPool().deref(thickness); !thick || thick->getKnotCount()!=1) |
| 36 | + { |
| 37 | + args.logger.log("Monochromatic Thickness node must be attached, but is %u of type %s",ELL_ERROR,thickness,args.pool->getTypeName(thickness).data()); |
| 38 | + return true; |
| 39 | + } |
35 | 40 | return false; |
36 | 41 | } |
37 | 42 |
|
@@ -111,18 +116,127 @@ bool CFrontendIR::CCookTorrance::invalid(const SInvalidCheckArgs& args) const |
111 | 116 | } |
112 | 117 |
|
113 | 118 |
|
114 | | -auto CFrontendIR::reciprocate(const typed_pointer_type<const IExprNode> other) -> typed_pointer_type<IExprNode> |
| 119 | +auto CFrontendIR::reciprocate(const typed_pointer_type<const IExprNode> orig) -> typed_pointer_type<const IExprNode> |
115 | 120 | { |
116 | | - if (const auto* in=getObjectPool().deref(block_allocator_type::_static_cast<const CFresnel>(other)); in) |
| 121 | + auto& pool = getObjectPool(); |
| 122 | + struct SEntry |
| 123 | + { |
| 124 | + typed_pointer_type<const IExprNode> handle; |
| 125 | + bool visited = false; |
| 126 | + }; |
| 127 | + core::vector<SEntry> stack; |
| 128 | + stack.reserve(32); |
| 129 | + stack.push_back({.handle=orig}); |
| 130 | + // use a hashmap because of holes in child arrays |
| 131 | + core::unordered_map<typed_pointer_type<const IExprNode>,typed_pointer_type<IExprNode>> substitutions; |
| 132 | + while (!stack.empty()) |
117 | 133 | { |
118 | | - auto fresnelH = getObjectPool().emplace<CFresnel>(); |
119 | | - auto* fresnel = getObjectPool().deref(fresnelH); |
120 | | - *fresnel = *in; |
121 | | - fresnel->reciprocateEtas = ~in->reciprocateEtas; |
122 | | - return fresnelH; |
| 134 | + auto& entry = stack.back(); |
| 135 | + const auto* const node = pool.deref(entry.handle); |
| 136 | + if (!node) // this is an error |
| 137 | + return {}; |
| 138 | + const auto childCount = node->getChildCount(); |
| 139 | + if (entry.visited) |
| 140 | + { |
| 141 | + entry.visited = true; |
| 142 | + for (uint8_t c=0; c<childCount; c++) |
| 143 | + { |
| 144 | + const auto childH = node->getChildHandle(c); |
| 145 | + if (auto child=pool.deref(childH); !child) |
| 146 | + continue; // this is not an error |
| 147 | + stack.push_back({.handle=childH}); |
| 148 | + } |
| 149 | + } |
| 150 | + else |
| 151 | + { |
| 152 | + const bool needToReciprocate = node->reciprocatable(); |
| 153 | + bool needToCopy = needToReciprocate; |
| 154 | + // if one descendant has changed then we need to copy node |
| 155 | + if (!needToCopy) |
| 156 | + { |
| 157 | + uint8_t c = 0; |
| 158 | + for (; c<childCount; c++) |
| 159 | + { |
| 160 | + if (auto found=substitutions.find(node->getChildHandle(c)); found!=substitutions.end()) |
| 161 | + break; |
| 162 | + } |
| 163 | + needToCopy = c!=childCount; |
| 164 | + } |
| 165 | + if (needToCopy) |
| 166 | + { |
| 167 | + const auto copyH = node->copy(this); |
| 168 | + // copy copies everything including children |
| 169 | + auto* const copy = pool.deref(copyH); |
| 170 | + if (!copy) |
| 171 | + return {}; |
| 172 | + if (needToReciprocate) |
| 173 | + node->reciprocate(copy); |
| 174 | + // only changed children need to be set |
| 175 | + for (uint8_t c=0; c<childCount; c++) |
| 176 | + { |
| 177 | + const auto childH = node->getChildHandle(c); |
| 178 | + if (!childH) |
| 179 | + continue; |
| 180 | + if (auto found=substitutions.find(childH); found!=substitutions.end()) |
| 181 | + copy->setChild(c,found->second); |
| 182 | + } |
| 183 | + substitutions.insert({entry.handle,copyH}); |
| 184 | + } |
| 185 | + stack.pop_back(); |
| 186 | + } |
| 187 | + } |
| 188 | + // there was nothing to reciprocate in the expression stack |
| 189 | + if (substitutions.empty()) |
| 190 | + return orig; |
| 191 | + return substitutions[orig]; |
| 192 | +} |
| 193 | + |
| 194 | +auto CFrontendIR::copyLayers(const typed_pointer_type<const CLayer> orig) -> typed_pointer_type<CLayer> |
| 195 | +{ |
| 196 | + auto& pool = getObjectPool(); |
| 197 | + auto copyH = pool.emplace<CLayer>(); |
| 198 | + { |
| 199 | + auto* outLayer = pool.deref(copyH); |
| 200 | + for (const auto* layer=pool.deref(orig); true; layer=pool.deref(layer->coated)) |
| 201 | + { |
| 202 | + *outLayer = *layer; |
| 203 | + if (!layer->coated) |
| 204 | + { |
| 205 | + // terminate the new stack |
| 206 | + outLayer->coated = {}; |
| 207 | + break; |
| 208 | + } |
| 209 | + // continue the new stack |
| 210 | + outLayer->coated = pool.emplace<CLayer>(); |
| 211 | + outLayer = pool.deref(outLayer->coated); |
| 212 | + } |
| 213 | + } |
| 214 | + return copyH; |
| 215 | +} |
| 216 | + |
| 217 | +auto CFrontendIR::reverse(const typed_pointer_type<const CLayer> orig) -> typed_pointer_type<CLayer> |
| 218 | +{ |
| 219 | + auto& pool = getObjectPool(); |
| 220 | + // we build the new linked list from the tail |
| 221 | + auto copyH = pool.emplace<CLayer>(); |
| 222 | + { |
| 223 | + auto* outLayer = pool.deref(copyH); |
| 224 | + typed_pointer_type<CLayer> underLayerH={}; |
| 225 | + for (const auto* layer=pool.deref(orig); true; layer=pool.deref(layer->coated)) |
| 226 | + { |
| 227 | + outLayer->coated = underLayerH; |
| 228 | + // we reciprocate everything because numerator and denominator switch (top and bottom of layer stack) |
| 229 | + outLayer->brdfBottom = reciprocate(layer->brdfTop)._const_cast(); |
| 230 | + outLayer->btdf = reciprocate(layer->btdf)._const_cast(); |
| 231 | + outLayer->brdfTop = reciprocate(layer->brdfBottom)._const_cast(); |
| 232 | + if (!layer->coated) |
| 233 | + break; |
| 234 | + underLayerH = copyH; |
| 235 | + copyH = pool.emplace<CLayer>(); |
| 236 | + outLayer = pool.deref(copyH); |
| 237 | + } |
123 | 238 | } |
124 | | - assert(false); // unimplemented |
125 | | - return {}; |
| 239 | + return copyH; |
126 | 240 | } |
127 | 241 |
|
128 | 242 | auto CFrontendIR::createNamedFresnel(const std::string_view name) -> typed_pointer_type<CFresnel> |
|
0 commit comments