Line data Source code
1 : /**
2 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "XL2dFrameContext.h"
24 : #include "XLFrameInfo.h"
25 : #include "XLCoreLoop.h"
26 : #include "XLCoreFrameRequest.h"
27 : #include "XLCoreFrameQueue.h"
28 : #include "XLDirector.h"
29 : #include "SPBitmap.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler::xenolith::basic2d {
32 :
33 9300 : bool ShadowLightInput::addAmbientLight(const Vec4 &pos, const Color4F &color, bool softShadow) {
34 9300 : if (ambientLightCount >= config::MaxAmbientLights) {
35 0 : return false;
36 : }
37 :
38 9300 : ambientLights[ambientLightCount++] = AmbientLightData{pos, color, uint32_t(softShadow ? 1 : 0)};
39 9300 : return true;
40 : }
41 :
42 0 : bool ShadowLightInput::addDirectLight(const Vec4 &pos, const Color4F &color, const Vec4 &data) {
43 0 : if (directLightCount >= config::MaxDirectLights) {
44 0 : return false;
45 : }
46 :
47 0 : directLights[directLightCount++] = DirectLightData{pos, color, data};
48 0 : return true;
49 : }
50 :
51 9279 : Extent2 ShadowLightInput::getShadowExtent(Size2 frameSize) const {
52 9279 : return Extent2(std::ceil((frameSize.width / sceneDensity) * shadowDensity),
53 18559 : std::ceil((frameSize.height / sceneDensity) * shadowDensity));
54 : }
55 :
56 4640 : Size2 ShadowLightInput::getShadowSize(Size2 frameSize) const {
57 9280 : return Size2((frameSize.width / sceneDensity) * shadowDensity,
58 4640 : (frameSize.height / sceneDensity) * shadowDensity);
59 : }
60 :
61 10 : void FrameContext2d::onEnter(Scene *scene) {
62 10 : FrameContext::onEnter(scene);
63 10 : if (!_init || _queue) {
64 10 : if (!initWithQueue(_queue)) {
65 0 : log::error("FrameContext2d", "Fail to initialize with queue:", _queue->getName());
66 : }
67 : }
68 10 : }
69 :
70 10 : void FrameContext2d::onExit() {
71 10 : FrameContext::onExit();
72 10 : }
73 :
74 4650 : Rc<FrameContextHandle> FrameContext2d::makeHandle(FrameInfo &frame) {
75 4650 : auto h = Rc<FrameContextHandle2d>::alloc();
76 4650 : h->director = frame.director;
77 4650 : h->context = this;
78 4650 : h->shadows = Rc<CommandList>::create(frame.pool);
79 4650 : h->commands = Rc<CommandList>::create(frame.pool);
80 9300 : return h;
81 4650 : }
82 :
83 4650 : void FrameContext2d::submitHandle(FrameInfo &frame, FrameContextHandle *handle) {
84 4650 : auto h = static_cast<FrameContextHandle2d *>(handle);
85 :
86 4650 : frame.resolvedInputs.emplace(_vertexAttachmentData);
87 4650 : frame.resolvedInputs.emplace(_lightAttachmentData);
88 4650 : frame.resolvedInputs.emplace(_shadowVertexAttachmentData);
89 4650 : frame.resolvedInputs.emplace(_sdfImageAttachmentData);
90 :
91 4650 : if (_materialDependency) {
92 51 : handle->waitDependencies.emplace_back(_materialDependency);
93 : }
94 :
95 9300 : frame.director->getGlLoop()->performOnGlThread(
96 4650 : [this, req = frame.request, q = _queue, dir = frame.director,
97 23250 : h = Rc<FrameContextHandle2d>(h)] () mutable {
98 :
99 4650 : req->addInput(_vertexAttachmentData, Rc<FrameContextHandle2d>(h));
100 4650 : req->addInput(_lightAttachmentData, Rc<FrameContextHandle2d>(h));
101 4650 : req->addInput(_shadowVertexAttachmentData, Rc<FrameContextHandle2d>(h));
102 4650 : req->addInput(_sdfImageAttachmentData, Rc<FrameContextHandle2d>(h));
103 :
104 4650 : req->setOutput(_sdfImageAttachmentData, [loop = dir->getGlLoop()] (core::FrameAttachmentData &data, bool success, Rc<Ref> &&ref) {
105 0 : loop->captureImage([] (const core::ImageInfoData &info, BytesView view) {
106 0 : Bitmap bmpSdf;
107 0 : bmpSdf.alloc(info.extent.width, info.extent.height, bitmap::PixelFormat::A8);
108 :
109 0 : Bitmap bmpHeight;
110 0 : bmpHeight.alloc(info.extent.width, info.extent.height, bitmap::PixelFormat::A8);
111 :
112 0 : auto dSdf = bmpSdf.dataPtr();
113 0 : auto dHgt = bmpHeight.dataPtr();
114 :
115 0 : while (!view.empty()) {
116 0 : auto value = view.readFloat16() / 16.0f;
117 :
118 0 : *dSdf = uint8_t(value * 255.0f);
119 0 : ++ dSdf;
120 :
121 0 : *dHgt = uint8_t((view.readFloat16() / 50.0f) * 255.0f);
122 0 : ++ dHgt;
123 : }
124 :
125 0 : bmpSdf.save(toString("sdf-image-", Time::now().toMicros(), ".png"));
126 0 : bmpHeight.save(toString("sdf-height-", Time::now().toMicros(), ".png"));
127 0 : }, data.image->getImage(), data.image->getLayout());
128 0 : return true;
129 : });
130 4650 : }, this);
131 :
132 4650 : FrameContext::submitHandle(frame, handle);
133 4650 : }
134 :
135 10 : bool FrameContext2d::initWithQueue(core::Queue *queue) {
136 100 : for (auto &it : queue->getAttachments()) {
137 90 : if (it->key == MaterialAttachmentName) {
138 10 : if (auto m = dynamic_cast<core::MaterialAttachment *>(it->attachment.get())) {
139 10 : _materialAttachmentData = it;
140 10 : readMaterials(m);
141 : }
142 : }
143 : }
144 :
145 50 : for (auto &it : queue->getInputAttachments()) {
146 40 : if (it->key == VertexAttachmentName) {
147 10 : _vertexAttachmentData = it;
148 30 : } else if (it->key == LightDataAttachmentName) {
149 10 : _lightAttachmentData = it;
150 20 : } else if (it->key == ShadowVertexAttachmentName) {
151 10 : _shadowVertexAttachmentData = it;
152 10 : } else if (it->key == SdfImageAttachmentName) {
153 10 : _sdfImageAttachmentData = it;
154 : }
155 : }
156 :
157 10 : return _materialAttachmentData && _vertexAttachmentData && _lightAttachmentData
158 20 : && _shadowVertexAttachmentData && _sdfImageAttachmentData;
159 : }
160 :
161 0 : bool StateData::init() {
162 0 : return true;
163 : }
164 :
165 370 : bool StateData::init(StateData *data) {
166 370 : if (data) {
167 0 : transform = data->transform;
168 0 : gradient = data->gradient;
169 : }
170 370 : return true;
171 : }
172 :
173 : }
|