Dust3D开源项目分析——渲染与材质部分 | 纹理生成 Part4
2021SC@SDUSCfor (const auto &it: partUvRects) {const auto &partId = it.first;const auto &rects = it.second;auto findSourceColorResult = partColorMap.find(partId);if (findSourceColorResult
·
2021SC@SDUSC
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
auto findSourceColorResult = partColorMap.find(partId);
if (findSourceColorResult != partColorMap.end()) {
const auto &color = findSourceColorResult->second;
QBrush brush(color);
float fillExpandSize = 2;
for (const auto &rect: rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize - fillExpandSize,
rect.top() * TextureGenerator::m_textureSize - fillExpandSize,
rect.width() * TextureGenerator::m_textureSize + fillExpandSize * 2,
rect.height() * TextureGenerator::m_textureSize + fillExpandSize * 2
};
texturePainter.fillRect(translatedRect, brush);
}
}
}
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
auto findMetalnessResult = partMetalnessMap.find(partId);
if (findMetalnessResult != partMetalnessMap.end()) {
if (qFuzzyCompare(findMetalnessResult->second, (float)0.0))
continue;
const auto &color = QColor(findMetalnessResult->second * 255,
findMetalnessResult->second * 255,
findMetalnessResult->second * 255);
QBrush brush(color);
float fillExpandSize = 2;
for (const auto &rect: rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize - fillExpandSize,
rect.top() * TextureGenerator::m_textureSize - fillExpandSize,
rect.width() * TextureGenerator::m_textureSize + fillExpandSize * 2,
rect.height() * TextureGenerator::m_textureSize + fillExpandSize * 2
};
textureMetalnessPainter.fillRect(translatedRect, brush);
hasMetalnessMap = true;
}
}
}
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
auto findRoughnessResult = partRoughnessMap.find(partId);
if (findRoughnessResult != partRoughnessMap.end()) {
if (qFuzzyCompare(findRoughnessResult->second, (float)1.0))
continue;
const auto &color = QColor(findRoughnessResult->second * 255,
findRoughnessResult->second * 255,
findRoughnessResult->second * 255);
QBrush brush(color);
float fillExpandSize = 2;
for (const auto &rect: rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize - fillExpandSize,
rect.top() * TextureGenerator::m_textureSize - fillExpandSize,
rect.width() * TextureGenerator::m_textureSize + fillExpandSize * 2,
rect.height() * TextureGenerator::m_textureSize + fillExpandSize * 2
};
textureRoughnessPainter.fillRect(translatedRect, brush);
hasRoughnessMap = true;
}
}
}
auto drawTexture = [&](const std::map<QUuid, std::pair<QPixmap, QPixmap>> &map, QPainter &painter, bool useAlpha) {
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
float alpha = 1.0;
if (useAlpha) {
auto findSourceColorResult = partColorMap.find(partId);
if (findSourceColorResult != partColorMap.end()) {
const auto &color = findSourceColorResult->second;
alpha = color.alphaF();
}
}
auto findTextureResult = map.find(partId);
if (findTextureResult != map.end()) {
const auto &pixmap = findTextureResult->second.first;
const auto &rotatedPixmap = findTextureResult->second.second;
painter.setOpacity(alpha);
for (const auto &rect: rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize,
rect.top() * TextureGenerator::m_textureSize,
rect.width() * TextureGenerator::m_textureSize,
rect.height() * TextureGenerator::m_textureSize
};
if (translatedRect.width() < translatedRect.height()) {
painter.drawTiledPixmap(translatedRect, rotatedPixmap, QPointF(rect.top(), rect.left()));
} else {
painter.drawTiledPixmap(translatedRect, pixmap, rect.topLeft());
}
}
painter.setOpacity(1.0);
}
}
};
auto convertTextureImageToPixmap = [&](const std::map<QUuid, std::pair<QImage, float>> &sourceMap,
std::map<QUuid, std::pair<QPixmap, QPixmap>> &targetMap) {
for (const auto &it: sourceMap) {
float tileScale = it.second.second;
const auto &image = it.second.first;
auto newSize = image.size() * tileScale;
QImage scaledImage = image.scaled(newSize);
QPoint center = scaledImage.rect().center();
QMatrix matrix;
matrix.translate(center.x(), center.y());
matrix.rotate(90);
auto rotatedImage = scaledImage.transformed(matrix).mirrored(true, false);
targetMap[it.first] = std::make_pair(QPixmap::fromImage(scaledImage),
QPixmap::fromImage(rotatedImage));
}
};
std::map<QUuid, std::pair<QPixmap, QPixmap>> partColorTexturePixmaps;
std::map<QUuid, std::pair<QPixmap, QPixmap>> partNormalTexturePixmaps;
std::map<QUuid, std::pair<QPixmap, QPixmap>> partMetalnessTexturePixmaps;
std::map<QUuid, std::pair<QPixmap, QPixmap>> partRoughnessTexturePixmaps;
std::map<QUuid, std::pair<QPixmap, QPixmap>> partAmbientOcclusionTexturePixmaps;
convertTextureImageToPixmap(m_partColorTextureMap, partColorTexturePixmaps);
convertTextureImageToPixmap(m_partNormalTextureMap, partNormalTexturePixmaps);
convertTextureImageToPixmap(m_partMetalnessTextureMap, partMetalnessTexturePixmaps);
convertTextureImageToPixmap(m_partRoughnessTextureMap, partRoughnessTexturePixmaps);
convertTextureImageToPixmap(m_partAmbientOcclusionTextureMap, partAmbientOcclusionTexturePixmaps);
drawTexture(partColorTexturePixmaps, texturePainter, true);
drawTexture(partNormalTexturePixmaps, textureNormalPainter, false);
drawTexture(partMetalnessTexturePixmaps, textureMetalnessPainter, false);
drawTexture(partRoughnessTexturePixmaps, textureRoughnessPainter, false);
drawTexture(partAmbientOcclusionTexturePixmaps, textureAmbientOcclusionPainter, false);
这一部分首先针对color、metalness、roughness贴图用QBrush进行绘制,前面三段for循环是完全并列的,分别处理color map,metalness map和roughness map。接下来将纹理图像转化为pixmap,建立QUuid到QPixmap的键值对完成纹理贴图的绘制。
drawTexture和convertTextureImageToPixmap这里使用的是C++ 11标准中的Lambda Function语法,实现了在generate()函数内部定义其他“函数”的功能,由于generate()函数本身跨度很大,这样处理提高了程序的可读性。
更多推荐
已为社区贡献1条内容
所有评论(0)