Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_phong_bumpmap_filter.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2010-2011 José Luis Vergara <pentalis@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
10
11#include "kis_debug.h"
12#include "kis_paint_device.h"
13#include "kis_config_widget.h"
14#include "KoUpdater.h"
15#include "kis_math_toolbox.h"
17#include <KoChannelInfo.h>
20#include "kis_iterator_ng.h"
21#include "kundo2command.h"
22#include "kis_painter.h"
23
25 : KisFilter(KoID("phongbumpmap", i18n("Phong Bumpmap")),
26 FiltersCategoryMapId, i18n("&Phong Bumpmap..."))
27{
31}
32
34 const QRect& applyRect,
35 const KisFilterConfigurationSP config,
36 KoUpdater *progressUpdater
37 ) const
38{
39 if (!config) return;
40
41 if (progressUpdater) progressUpdater->setProgress(0);
42
43 QString userChosenHeightChannel = config->getString(PHONG_HEIGHT_CHANNEL, "FAIL");
44 bool m_usenormalmap = config->getBool(USE_NORMALMAP_IS_ENABLED);
45
46 if (userChosenHeightChannel == "FAIL") {
47 return;
48 }
49
50 const QList<KoChannelInfo*> channels = device->colorSpace()->channels();
51 KoChannelInfo *m_heightChannel = 0;
52
53 Q_FOREACH (KoChannelInfo* channel, channels) {
54 if (userChosenHeightChannel == channel->name()) {
55 m_heightChannel = channel;
56 }
57 }
58
59 if (!m_heightChannel) {
60 m_heightChannel = channels.first();
61 }
62 KIS_ASSERT_RECOVER_RETURN(m_heightChannel);
63
64 QRect inputArea = applyRect;
65 QRect outputArea = applyRect;
66 if (m_usenormalmap==false) {
67 inputArea.adjust(-1, -1, 1, 1);
68 }
69
70 quint32 posup;
71 quint32 posdown;
72 quint32 posleft;
73 quint32 posright;
74 QColor I; //Reflected light
75
76 if (progressUpdater) progressUpdater->setProgress(1);
77
78 //======Preparation paraphernalia=======
79
80 //Hardcoded facts about Phong Bumpmap: it _will_ generate an RGBA16 bumpmap
81 const quint8 BYTE_DEPTH_OF_BUMPMAP = 2; // 16 bits per channel
82 const quint8 CHANNEL_COUNT_OF_BUMPMAP = 4; // RGBA
83 const quint32 pixelsOfInputArea = abs(inputArea.width() * inputArea.height());
84 const quint32 pixelsOfOutputArea = abs(outputArea.width() * outputArea.height());
85 const quint8 pixelSize = BYTE_DEPTH_OF_BUMPMAP * CHANNEL_COUNT_OF_BUMPMAP;
86 const quint32 bytesToFillBumpmapArea = pixelsOfOutputArea * pixelSize;
87 QVector<quint8> bumpmap(bytesToFillBumpmapArea);
88 quint8 *bumpmapDataPointer = bumpmap.data();
89 quint32 ki = KoChannelInfo::displayPositionToChannelIndex(m_heightChannel->displayPosition(), channels);
90 PhongPixelProcessor tileRenderer(pixelsOfInputArea, config);
91
92
93 if (progressUpdater) progressUpdater->setProgress(2);
94
95 //===============RENDER=================
96
97 QVector<PtrToDouble> toDoubleFuncPtr(channels.count());
98 KisMathToolbox mathToolbox;
99 if (!mathToolbox.getToDoubleChannelPtr(channels, toDoubleFuncPtr)) {
100 return;
101 }
102
104 quint32 curPixel = 0;
105 iterator = device->createHLineConstIteratorNG(inputArea.x(),
106 inputArea.y(),
107 inputArea.width()
108 );
109
110 if (m_usenormalmap==false) {
111 for (qint32 srcRow = 0; srcRow < inputArea.height(); ++srcRow) {
112 do {
113 const quint8 *data = iterator->oldRawData();
114 tileRenderer.realheightmap[curPixel] = toDoubleFuncPtr[ki](data, channels[ki]->pos());
115 curPixel++;
116 }
117 while (iterator->nextPixel());
118 iterator->nextRow();
119 }
120 if (progressUpdater) progressUpdater->setProgress(50);
121
122 const int tileHeightMinus1 = inputArea.height() - 1;
123 const int tileWidthMinus1 = inputArea.width() - 1;
124
125 // Foreach INNER pixel in tile
126 for (int y = 1; y < tileHeightMinus1; ++y) {
127 for (int x = 1; x < tileWidthMinus1; ++x) {
128 posup = (y + 1) * inputArea.width() + x;
129 posdown = (y - 1) * inputArea.width() + x;
130 posleft = y * inputArea.width() + x - 1;
131 posright = y * inputArea.width() + x + 1;
132
133
134 memcpy(bumpmapDataPointer,
135 tileRenderer.IlluminatePixelFromHeightmap(posup, posdown, posleft, posright).data(),
136 pixelSize);
137
138 bumpmapDataPointer += pixelSize;
139 }
140 }
141 } else {
142 for (qint32 srcRow = 0; srcRow < inputArea.height(); ++srcRow) {
143 do {
144 const quint8 *data = iterator->oldRawData();
145 tileRenderer.realheightmap[curPixel] = toDoubleFuncPtr[ki](data, channels[ki]->pos());
146 QVector <float> current_pixel_values(4);
147 device->colorSpace()->normalisedChannelsValue(data, current_pixel_values );
148
149 //dbgKrita<< "Vector:" << current_pixel_values[2] << "," << current_pixel_values[1] << "," << current_pixel_values[0];
150 memcpy(bumpmapDataPointer,
151 tileRenderer.IlluminatePixelFromNormalmap(current_pixel_values[2], current_pixel_values[1], current_pixel_values[0]).data(),
152 pixelSize);
153
154 curPixel++;
155 //pointer that crashes here, but not in the other if statement.
156 bumpmapDataPointer += pixelSize;
157
158
159
160 }
161 while (iterator->nextPixel());
162 iterator->nextRow();
163 }
164 }
165
166 if (progressUpdater) progressUpdater->setProgress(90);
167
168 KisPaintDeviceSP bumpmapPaintDevice = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb16());
169 bumpmapPaintDevice->writeBytes(bumpmap.data(), outputArea.x(), outputArea.y(), outputArea.width(), outputArea.height());
171 KisPainter copier(device);
172 copier.bitBlt(outputArea.x(), outputArea.y(), bumpmapPaintDevice,
173 outputArea.x(), outputArea.y(), outputArea.width(), outputArea.height());
174 //device->prepareClone(bumpmapPaintDevice);
175 //device->makeCloneFrom(bumpmapPaintDevice, bumpmapPaintDevice->extent()); // THIS COULD BE BUG GY
176
177 if (progressUpdater) progressUpdater->setProgress(100);
178}
179
181{
182 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
183 config->setProperty(PHONG_AMBIENT_REFLECTIVITY, 0.2);
184 config->setProperty(PHONG_DIFFUSE_REFLECTIVITY, 0.5);
185 config->setProperty(PHONG_SPECULAR_REFLECTIVITY, 0.3);
186 config->setProperty(PHONG_SHINYNESS_EXPONENT, 2);
187 config->setProperty(USE_NORMALMAP_IS_ENABLED, false);
188 config->setProperty(PHONG_DIFFUSE_REFLECTIVITY_IS_ENABLED, true);
189 config->setProperty(PHONG_SPECULAR_REFLECTIVITY_IS_ENABLED, true);
190 // Indexes are off by 1 simply because arrays start at 0 and the GUI naming scheme started at 1
191 config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[0], true);
192 config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[1], true);
193 config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[2], false);
194 config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[3], false);
195 config->setProperty(PHONG_ILLUMINANT_COLOR[0], QColor(255, 255, 0));
196 config->setProperty(PHONG_ILLUMINANT_COLOR[1], QColor(255, 0, 0));
197 config->setProperty(PHONG_ILLUMINANT_COLOR[2], QColor(0, 0, 255));
198 config->setProperty(PHONG_ILLUMINANT_COLOR[3], QColor(0, 255, 0));
199 config->setProperty(PHONG_ILLUMINANT_AZIMUTH[0], 50);
200 config->setProperty(PHONG_ILLUMINANT_AZIMUTH[1], 100);
201 config->setProperty(PHONG_ILLUMINANT_AZIMUTH[2], 150);
202 config->setProperty(PHONG_ILLUMINANT_AZIMUTH[3], 200);
203 config->setProperty(PHONG_ILLUMINANT_INCLINATION[0], 25);
204 config->setProperty(PHONG_ILLUMINANT_INCLINATION[1], 20);
205 config->setProperty(PHONG_ILLUMINANT_INCLINATION[2], 30);
206 config->setProperty(PHONG_ILLUMINANT_INCLINATION[3], 40);
207 return config;
208}
209
210QRect KisFilterPhongBumpmap::neededRect(const QRect &rect, const KisFilterConfigurationSP /*config*/, int /*lod*/) const
211{
212 return rect.adjusted(-1, -1, 1, 1);
213}
214
215QRect KisFilterPhongBumpmap::changedRect(const QRect &rect, const KisFilterConfigurationSP /*config*/, int /*lod*/) const
216{
217 return rect;
218}
219
221{
223 return w;
224}
225
226
@ TO_LAB16
virtual const quint8 * oldRawData() const =0
virtual bool nextPixel()=0
void processImpl(KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const override
QRect neededRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const override
QRect changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const override
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
void setSupportsLevelOfDetail(bool value)
virtual void nextRow()=0
bool getToDoubleChannelPtr(QList< KoChannelInfo * > cis, QVector< PtrToDouble > &f)
const KoColorSpace * colorSpace() const
void convertTo(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags(), KUndo2Command *parentCommand=nullptr, KoUpdater *progressUpdater=nullptr)
KisHLineConstIteratorSP createHLineConstIteratorNG(qint32 x, qint32 y, qint32 w) const
void writeBytes(const quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h)
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
static int displayPositionToChannelIndex(int displayPosition, const QList< KoChannelInfo * > &channels)
QString name() const
qint32 displayPosition() const
QList< KoChannelInfo * > channels
virtual void normalisedChannelsValue(const quint8 *pixel, QVector< float > &channels) const =0
Definition KoID.h:30
void setProgress(int percent)
Definition KoUpdater.cpp:38
QVector< quint16 > IlluminatePixelFromHeightmap(quint32 posup, quint32 posdown, quint32 posleft, quint32 posright)
QVector< double > realheightmap
QVector< quint16 > IlluminatePixelFromNormalmap(qreal r, qreal g, qreal b)
void bumpmap(KisPixelSelectionSP device, const QRect &selectionRect, const bumpmap_vals_t &bmvals)
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
const KoID FiltersCategoryMapId("map_filters", ki18nc("The category of mapping filters, like bump map or gradient filter map. Verb.", "Map"))
const QString PHONG_SPECULAR_REFLECTIVITY_IS_ENABLED
const QString PHONG_DIFFUSE_REFLECTIVITY_IS_ENABLED
const QString PHONG_HEIGHT_CHANNEL
const QString PHONG_ILLUMINANT_AZIMUTH[]
const QString PHONG_ILLUMINANT_INCLINATION[]
const QString PHONG_ILLUMINANT_COLOR[]
const QString PHONG_SHINYNESS_EXPONENT
const QString PHONG_DIFFUSE_REFLECTIVITY
const QString PHONG_ILLUMINANT_IS_ENABLED[]
const QString USE_NORMALMAP_IS_ENABLED
const QString PHONG_SPECULAR_REFLECTIVITY
const QString PHONG_AMBIENT_REFLECTIVITY
virtual KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setSupportsPainting(bool v)
void setColorSpaceIndependence(ColorSpaceIndependence v)
static KoColorSpaceRegistry * instance()