渲染SDK 0.1.2
载入中...
搜索中...
未找到
光照设置示例

概述

本教程提供了光照设置使用教程

描述

通过光照模块设置光照参数

示例代码

效果图

光照设置
光照设置

main.cpp

#include <QApplication>
#include "Mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Mainwindow w;
w.show();
return a.exec();
}

Mainwindow.h

#pragma once
#include <QWidget>
#include <AMCAXRender.h>
class QColorDialog;
class LightPropertyView;
class Mainwindow : public QWidget
{
Q_OBJECT
public:
Mainwindow(QWidget* parent = nullptr);
~Mainwindow();
private:
void CreateSphere();
QColorDialog* colorDialog;
std::shared_ptr<AMCAXRender::IRenderComponent> mRenderComponent;
std::shared_ptr<AMCAXRender::CBasicRender> mRender;
LightPropertyView* m_lightProperty;
};
Component Creation

Mainwindow.cpp

#include "Mainwindow.h"
#include <QGridLayout>
#include <QColorDialog>
#include <QMouseEvent>
#include <iostream>
#include <QDebug>
#include "LightPropertyView.h"
#ifdef USE_AMCAX_KERNEL
#include <modeling/MakeShapeTool.hpp>
#include <modeling/MakeSphere.hpp>
#endif
Mainwindow::Mainwindow(QWidget* parent)
: QWidget(parent)
{
//ui.setupUi(this);
//初始化
mRenderComponent = AMCAXRender::CreateRenderComponent(this);
mRender = mRenderComponent->CreateBasicRender();
QRect rect(800, 600, 800, 600);
setGeometry(rect);
QHBoxLayout* layout = new QHBoxLayout;
layout->addWidget(mRender->widget, 1);
mRender->widget->show();
setLayout(layout);
colorDialog = new QColorDialog(this);
colorDialog->setVisible(false);
m_lightProperty = new LightPropertyView(mRender->lightManager, this);
layout->addWidget(m_lightProperty, 0);
CreateSphere();
}
Mainwindow::~Mainwindow()
{
}
void Mainwindow::CreateSphere()
{
#ifdef USE_AMCAX_KERNEL
AMCAX::TopoShape sphere = AMCAX::MakeSphere(10);
auto sphereEntity = mRender->entityFactory->FromShape(sphere);
mRender->entityManage->ClearPreview();
mRender->entityManage->AddEntity(sphereEntity);
double rgb[3] = { 1.0, 0.0, 0.0 };
mRender->entityManage->SetEntityColor(sphereEntity->GetEntityId(), rgb);
mRender->cameraManage->ResetCamera();
mRender->styleManage->ShowTitleMenu(0);
mRender->entityManage->DoRepaint();
#endif // USE_AMCAX_KERNEL
}
AMCAX_RENDER_API std::shared_ptr< IRenderComponent > CreateRenderComponent(QWidget *parent)
Create Render Component

ColorPicker.h

#include <QApplication>
#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>
#include <QFrame>
#include <QColorDialog>
#include <QMouseEvent>
#include <QPushButton>
// 自定义颜色选择控件
class ColorPicker : public QWidget {
Q_OBJECT
public:
ColorPicker(const QString& text, QWidget* parent = nullptr)
: QWidget(parent), color(Qt::white)
{
// 横向布局:标签 + 颜色框
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
QPushButton* pushButton = new QPushButton(parent);
pushButton->setText(text);
layout->addWidget(pushButton);
// 颜色预览框
colorFrame = new QFrame;
colorFrame->setFixedSize(60, 24); // 设置固定大小
colorFrame->setFrameShape(QFrame::Box); // 边框样式
colorFrame->setLineWidth(1); // 边框宽度
colorFrame->setStyleSheet("background-color: " + color.name() + ";");
layout->addWidget(colorFrame);
// 允许点击标签触发颜色选择
pushButton->installEventFilter(this);
}
// 获取当前颜色
QColor getColor() const { return color; }
void setColor(const QColor& color)
{
colorFrame->setStyleSheet("background-color: " + color.name() + ";");
}
signals:
void colorChanged(const QColor& color);
protected:
bool eventFilter(QObject* obj, QEvent* event) override {
// 处理标签或颜色框的点击事件
if (event->type() == QEvent::MouseButtonPress) {
QColor newColor = QColorDialog::getColor(color, this, "选择颜色");
if (newColor.isValid()) {
color = newColor;
colorFrame->setStyleSheet("background-color: " + color.name() + ";");
emit colorChanged(color);
}
return true;
}
return QWidget::eventFilter(obj, event);
}
private:
QFrame* colorFrame;
QColor color;
};

LightModel.h

#pragma once
#include <QAbstractTableModel>
#include <memory>
struct Light
{
QString name;
int id;
int type;
std::array<float, 3> diffuse{1,0,0};
//std::array<float, 3> ambient{1,1,1};
//std::array<float, 3> specular{1,1,1};
std::array<float, 3> position{0,0,0};
float constantAtten{ 1.0 };
float linearAtten{ 0.0 };
float quadraticAtten{ 0.0 };
float spotAngle{ 30.f };
float spotExponent{ 1.0f };
std::array<float, 3> focalPoint{0,0,1};
};
class LightModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit LightModel(QObject* parent) : QAbstractTableModel(parent) {}
int rowCount(const QModelIndex& parent = QModelIndex()) const override
{
return m_lights.size();
}
int columnCount(const QModelIndex& parent = QModelIndex()) const override
{
return 2;
}
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole)const override
{
if (!index.isValid() || role != Qt::DisplayRole)
{
return QVariant();
}
std::shared_ptr<Light> light = m_lights[index.row()];
switch (index.column())
{
case 0:
return light->name;
case 1:
return light->id;
default:
return QVariant();
}
}
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
switch (section)
{
case 0:
return "Name";
case 1:
return "ID";
default:
return QVariant();
}
}
return QVariant();
}
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override
{
if (!index.isValid() || role != Qt::EditRole)
{
return false;
}
std::shared_ptr<Light> light = m_lights[index.row()];
switch (index.column())
{
case 0:
light->name = value.toString();
break;
case 1:
light->id = value.toInt();
break;
default:
break;
}
emit dataChanged(index, index);
return true;
}
void addLight(std::shared_ptr<AMCAXRender::Light> light)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
auto param = extract(light);
m_lights.append(param);
endInsertRows();
}
void removeLight(int row)
{
if (row < 0 || row > rowCount())
{
return;
}
beginRemoveRows(QModelIndex(), row, row);
m_lights.remove(row);
endRemoveRows();
}
std::shared_ptr<Light> getLight(int row)
{
if (row < 0 || row >= m_lights.size())
{
return nullptr;
}
return m_lights[row];
}
void updateLight(int row, const std::shared_ptr<Light>& newData)
{
if (row < 0 || row >= rowCount()) return;
auto light = m_lights[row];
light = newData;
// 通知所有列数据变化
QModelIndex topLeft = createIndex(row, 0);
QModelIndex bottomRight = createIndex(row, columnCount() - 1);
emit dataChanged(topLeft, bottomRight);
}
static std::shared_ptr<Light> extract(std::shared_ptr<AMCAXRender::Light> light)
{
std::shared_ptr<Light> lit = std::make_shared<Light>();
QString lightName = QString("Light_%1").arg(light->GetLightID());
lit->name = lightName;
lit->id = light->GetLightID();
//lit->ambient = light->GetAmbient();
//lit->specular = light->GetSpecular();""
lit->diffuse = light->GetColor();
lit->type = (int)light->GetType();
lit->position = light->GetPosition();
return lit;
}
private:
QVector< std::shared_ptr<Light>> m_lights;
};
Light Class File

LightPropertyView.h

#pragma once
#include <QtWidgets/qwidget.h>
#include <QVBoxLayout>
#include <QLineEdit>
#include "Interface/LightManager.h"
#include "LightModel.h"
class LightModel;
class QTableView;
class QTableWidget;
class QGroupBox;
class QComboBox;
class ColorPicker;
class QSlider;
class QDoubleSpinBox;
class QPushButton;
class LightPropertyView : public QWidget
{
Q_OBJECT
public:
explicit LightPropertyView(std::shared_ptr<AMCAXRender::LightManager> render, QWidget* parent = nullptr);
protected:
void closeEvent(QCloseEvent* event) override;
private Q_SLOTS:
void onTypeChanged(int current);
void createLight();
void apply();
void onRowChanged(QModelIndex index);
private:
void initUI();
void initType();
void initPostion();
void initIntensity();
void initSpot();
void initParameter();
void initLightTable();
void setupUI();
void createDefaultLight();
void moveToRight(QWidget* parent);
template <typename Setter>
void bindLineEdit(QLineEdit* editor, Setter set)
{
connect(editor, &QLineEdit::textChanged, [=](const QString& str) {
if (m_currentRow == -1)
{
return;
}
auto light = m_lightModel->getLight(m_currentRow);
bool ok;
float value = str.toFloat(&ok);
if (ok) {
set(light, value);
m_lightModel->updateLight(m_currentRow, light);
editor->setStyleSheet("");
}
else {
editor->setStyleSheet("background-color: #FFE4E1;");
}
});
}
std::shared_ptr<AMCAXRender::LightManager> m_lightManager;
std::shared_ptr<AMCAXRender::Light> m_curLight;
LightModel* m_lightModel;
QTableView* m_tableView;
QVBoxLayout* m_mainLayout;
QTableWidget* m_lightTable;
QComboBox* m_typeCombo;
QGroupBox* m_spotGroup;
QGroupBox* m_intensityGroup;
QLineEdit* m_editX;
QLineEdit* m_editY;
QLineEdit* m_editZ;
ColorPicker* m_colorPicker;
QSlider* m_constantAtten;
QSlider* m_linearAtten;
QSlider* m_quadraticAtten;
std::array<float, 3> m_position{0.0, 0.0, 0.0};
QColor m_color;
QPushButton* m_destroyButton;
float m_constantAttenuation{ 1.0 };
float m_linearAttenuation{ 0.0 };
float m_quadraticAttenuation{ 0.0 };
int m_currentRow{ 0 };
QString m_defaultLightName;
float m_spotAngle{ 30. };
QSlider* m_exponenEdit;
QDoubleSpinBox* m_focalX;
QDoubleSpinBox* m_focalY;
QDoubleSpinBox* m_focalZ;
};

LightPropertyView.cpp

#include "LightPropertyView.h"
#include "ColorPicker.h"
#include "LightModel.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTableWidget>
#include <QComboBox>
#include <QHeaderView>
#include <QHBoxLayout>
#include <QFormLayout>
#include <QLineEdit>
#include <QGroupBox>
#include <QCheckBox>
#include <QSpinBox>
const int QSlider_Range = 10;
enum TableColumn {
COLUMN_NAME = 0,
COLUMN_ID = 1
};
LightPropertyView::LightPropertyView(std::shared_ptr<AMCAXRender::LightManager> lightManager, QWidget* parent)
: QWidget(parent)
{
//setWindowTitle("Light Property Setting");
m_lightManager = lightManager;
m_mainLayout = new QVBoxLayout(this);
m_mainLayout->setAlignment(Qt::AlignTop);
m_mainLayout->setSpacing(10);
this->setLayout(m_mainLayout);
initUI();
createDefaultLight();
//moveToRight(parent);
setupUI();
show();
}
void LightPropertyView::closeEvent(QCloseEvent* event)
{
hide();
}
void LightPropertyView::createDefaultLight()
{
m_curLight = m_lightManager->CreateLight();
m_curLight->SetPostion({ 20, 0,0 });
m_curLight->SetLightEnable(true);
m_defaultLightName = QString("Light_%1").arg(m_curLight->GetLightID());
m_lightModel->addLight(m_curLight);
}
void LightPropertyView::moveToRight(QWidget* parent)
{
if (parent)
{
QPoint p = parent->rect().topRight();
QPoint parentRight = mapToGlobal(p);
QPoint p1 = rect().topRight();
QPoint childParent = mapToGlobal(p1);
int x = parentRight.x() - childParent.x() - rect().width();
int y = parentRight.y() - childParent.y();
move(x, y);
}
}
void LightPropertyView::initUI()
{
initLightTable();
initType();
initParameter();
initPostion();
initIntensity();
initSpot();
}
void LightPropertyView::setupUI()
{
onTypeChanged(0);
m_tableView->selectRow(0);
}
void LightPropertyView::initType()
{
// 类型下拉框
m_typeCombo = new QComboBox;
m_typeCombo->addItems({ "Direction", "Point", "Spot" });
QGroupBox* typeGroup = new QGroupBox("Type");
QVBoxLayout* typeLayout = new QVBoxLayout(typeGroup);
typeLayout->addWidget(m_typeCombo);
m_mainLayout->addWidget(typeGroup);
connect(m_typeCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &LightPropertyView::onTypeChanged);
}
void LightPropertyView::onTypeChanged(int curr)
{
if (m_curLight)
{
m_curLight->SetType((AMCAXRender::LightType)curr);
auto light = m_lightModel->getLight(m_currentRow);
light->type = curr;
}
switch (curr)
{
case 0:
m_spotGroup->setEnabled(false);
m_intensityGroup->setEnabled(false);
break;
case 1:
m_spotGroup->setEnabled(false);
m_intensityGroup->setEnabled(true);
break;
case 2:
m_spotGroup->setEnabled(true);
m_intensityGroup->setEnabled(true);
break;
default:
break;
}
}
void LightPropertyView::initPostion()
{
// 位置编辑框
QGroupBox* position = new QGroupBox("Position");
QFormLayout* rightLayout = new QFormLayout(position);
m_editX = new QLineEdit("0");
m_editY = new QLineEdit("0");
m_editZ = new QLineEdit("0");
rightLayout->addRow("Position X:", m_editX);
rightLayout->addRow("Position Y:", m_editY);
rightLayout->addRow("Position Z:", m_editZ);
m_mainLayout->addWidget(position);
connect(m_editX, &QLineEdit::textChanged, [this](const QString& text) {
m_position[0] = text.toFloat();
m_curLight->SetPostion(m_position);
});
connect(m_editY, &QLineEdit::textChanged, [this](const QString& text) {
m_position[1] = text.toFloat();
m_curLight->SetPostion(m_position);
});
connect(m_editZ, &QLineEdit::textChanged, [this](const QString& text) {
m_position[2] = text.toFloat();
m_curLight->SetPostion(m_position);
});
bindLineEdit(m_editX, [](std::shared_ptr< Light> light, float val) { light->position[0] = val; });
bindLineEdit(m_editY, [](std::shared_ptr< Light> light, float val) { light->position[1] = val; });
bindLineEdit(m_editZ, [](std::shared_ptr< Light> light, float val) { light->position[2] = val; });
}
void LightPropertyView::initIntensity()
{
//intensity 编辑
m_intensityGroup = new QGroupBox("Intensity");
m_constantAtten = new QSlider(Qt::Horizontal);
m_constantAtten->setRange(0, QSlider_Range);
m_linearAtten = new QSlider(Qt::Horizontal);
m_linearAtten->setRange(0, QSlider_Range);
m_quadraticAtten = new QSlider(Qt::Horizontal);
m_quadraticAtten->setRange(0, QSlider_Range);
QVBoxLayout* intensityLayout = new QVBoxLayout();
intensityLayout->addWidget(m_constantAtten);
intensityLayout->addWidget(m_linearAtten);
intensityLayout->addWidget(m_quadraticAtten);
m_intensityGroup->setLayout(intensityLayout);
m_mainLayout->addWidget(m_intensityGroup);
connect(m_constantAtten, &QSlider::valueChanged, [this](int value) {
m_constantAttenuation = value;
m_curLight->SetAttenuation({ m_constantAttenuation, m_linearAttenuation, m_quadraticAttenuation });
auto light = m_lightModel->getLight(m_currentRow);
light->constantAtten = value;
});
connect(m_linearAtten, &QSlider::valueChanged, [this](int value) {
m_linearAttenuation = value;
m_curLight->SetAttenuation({ m_constantAttenuation, m_linearAttenuation, m_quadraticAttenuation });
auto light = m_lightModel->getLight(m_currentRow);
light->linearAtten = value;
});
connect(m_quadraticAtten, &QSlider::valueChanged, [this](int value) {
m_quadraticAttenuation = value;
m_curLight->SetAttenuation({ m_constantAttenuation, m_linearAttenuation, m_quadraticAttenuation });
auto light = m_lightModel->getLight(m_currentRow);
light->quadraticAtten = value;
});
}
void LightPropertyView::initSpot()
{
//spot 参数编辑
m_spotGroup = new QGroupBox("spot");
QGridLayout* spotLayout = new QGridLayout(m_spotGroup);
spotLayout->addWidget(new QLabel("Angle"), 0, 0);
auto angleEdit = new QSpinBox(m_spotGroup);
angleEdit->setRange(0, 90);
spotLayout->addWidget(angleEdit, 0, 1);
spotLayout->addWidget(new QLabel("FocalPointX"), 1, 0);
m_focalX = new QDoubleSpinBox(m_spotGroup);
m_focalX->setRange(-200.0, 200.0);
spotLayout->addWidget(m_focalX, 1, 1);
spotLayout->addWidget(new QLabel("FocalPointY"), 2, 0);
m_focalY = new QDoubleSpinBox(m_spotGroup);
m_focalY->setRange(-200.0, 200.0);
spotLayout->addWidget(m_focalY, 2, 1);
spotLayout->addWidget(new QLabel("FocalPointZ"), 3, 0);
m_focalZ = new QDoubleSpinBox(m_spotGroup);
m_focalZ->setRange(-200.0, 200.0);
spotLayout->addWidget(m_focalZ, 3, 1);
m_mainLayout->addWidget(m_spotGroup);
m_exponenEdit = new QSlider(Qt::Horizontal);
m_exponenEdit->setRange(0, 100);
spotLayout->addWidget(m_exponenEdit);
connect(angleEdit, &QSpinBox::valueChanged, [this](int val) {
auto light = m_lightModel->getLight(m_currentRow);
light->spotAngle = (float)val;
m_curLight->SetSpotConeAngle((float)val);
});
connect(m_focalX, &QDoubleSpinBox::valueChanged, [this](double x) {
auto light = m_lightModel->getLight(m_currentRow);
light->focalPoint[0] = (float)x;
m_curLight->SetFocalPoint(light->focalPoint);
});
connect(m_focalY, &QDoubleSpinBox::valueChanged, [this](double x) {
auto light = m_lightModel->getLight(m_currentRow);
light->focalPoint[1] = (float)x;
m_curLight->SetFocalPoint(light->focalPoint);
});
connect(m_focalZ, &QDoubleSpinBox::valueChanged, [this](double x) {
auto light = m_lightModel->getLight(m_currentRow);
light->focalPoint[2] = (float)x;
m_curLight->SetFocalPoint(light->focalPoint);
});
connect(m_exponenEdit, &QSlider::valueChanged, [this](int val) {
auto light = m_lightModel->getLight(m_currentRow);
light->spotExponent = (float)val;
m_curLight->SetSpotExponent((float)val);
});
}
void LightPropertyView::initParameter()
{
// 颜色编辑框
QGroupBox* paramGroup = new QGroupBox("Parameter");
QVBoxLayout* paramLayout = new QVBoxLayout(paramGroup);
// 创建三个颜色选择器
m_colorPicker = new ColorPicker("Color");
// 添加到布局
paramLayout->addWidget(m_colorPicker);
m_mainLayout->addWidget(paramGroup);
connect(m_colorPicker, &ColorPicker::colorChanged, [this](const QColor& color) {
m_color = color;
m_curLight->SetColor({ m_color.redF() , m_color.greenF() , m_color.blueF() });
auto light = m_lightModel->getLight(m_currentRow);
std::array<float, 3> diffuse = { color.redF(), color.greenF(), color.blueF() };
light->diffuse = diffuse;
});
}
void LightPropertyView::initLightTable()
{
m_tableView = new QTableView();
m_lightModel = new LightModel(this);
m_tableView->setModel(m_lightModel);
m_tableView->horizontalHeader()->setVisible(true);
m_tableView->horizontalHeader()->setStyleSheet("QHeaderView::section{background:skyblue;color:black;}");
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
m_mainLayout->addWidget(m_tableView);
auto createButton = new QPushButton("create");
m_destroyButton = new QPushButton("destroy");
QHBoxLayout* hLayout = new QHBoxLayout();
hLayout->addWidget(createButton);
hLayout->addWidget(m_destroyButton);
m_mainLayout->addLayout(hLayout);
connect(createButton, &QPushButton::clicked, [this]() {
createLight();
});
connect(m_destroyButton, &QPushButton::clicked, [this]() {
QModelIndexList selected = m_tableView->selectionModel()->selectedRows();
if (!selected.isEmpty()) {
for (const auto& select : selected)
{
QModelIndex cellIndex = m_lightModel->index(select.row(), 1);
auto rows = m_lightModel->rowCount();
m_lightManager->RemoveLight(m_lightModel->data(cellIndex).toInt());
m_lightModel->removeLight(select.row());
}
}
});
connect(m_tableView->selectionModel(), &QItemSelectionModel::currentRowChanged,
this, &LightPropertyView::onRowChanged);
}
void LightPropertyView::createLight()
{
m_curLight = m_lightManager->CreateLight();
m_curLight->SetLightEnable(true);
m_lightModel->addLight(m_curLight);
}
void LightPropertyView::apply()
{
if (m_curLight)
{
m_curLight->SetColor({ m_color.redF() , m_color.greenF() , m_color.blueF() });
}
}
void LightPropertyView::onRowChanged(const QModelIndex current) {
m_currentRow = current.row();
if (m_currentRow == -1) return;
// 从模型获取数据并显示
auto light = m_lightModel->getLight(m_currentRow);
m_editX->setText(QString::number(light->position[0]));
m_editY->setText(QString::number(light->position[1]));
m_editZ->setText(QString::number(light->position[2]));
QColor color;
color.setRgbF(light->diffuse[0], light->diffuse[1], light->diffuse[2]);
m_colorPicker->setColor(color);
//color.setRgbF(light->ambient[0], light->ambient[1], light->ambient[2]);
//m_ambientPicker->setColor(color);
//color.setRgbF(light->specular[0], light->specular[1], light->specular[2]);
//m_specularPicker->setColor(color);
m_typeCombo->setCurrentIndex(light->type);
m_constantAtten->setValue(light->constantAtten);
m_linearAtten->setValue(light->linearAtten);
m_quadraticAtten->setValue(light->quadraticAtten);
if (light->name == m_defaultLightName)
{
m_destroyButton->setEnabled(false);
}
else
{
m_destroyButton->setEnabled(true);
}
}
LightType
Light type
定义 Constants.h:298

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(LightSample)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
add_definitions(-DUSE_AMCAX_KERNEL)
set(AMCAX_components AMCAXCommon AMCAXPart AMCAXStep AMCAXOCCTIO)
find_package(AMCAXCommon REQUIRED)
find_package(AMCAXStep REQUIRED)
find_package(AMCAXPart REQUIRED)
find_package(AMCAXOCCTIO REQUIRED)
list(APPEND CMAKE_PREFIX_PATH ${AMCAXRender_PATH})
find_package(AMCAXRender )
find_package(Qt6 COMPONENTS Widgets Core Gui REQUIRED)
file(GLOB ALL_UI_FILES *.ui)
file(GLOB ALL_FILES *.cpp *.h)
add_executable(${PROJECT_NAME} ${ALL_UI_FILES} ${ALL_FILES})
target_link_libraries(${PROJECT_NAME} PRIVATE ${AMCAX_components})
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)
target_link_libraries(${PROJECT_NAME} PRIVATE AMCAXRender::AMCAXRender)

更多

更多属性请参考 AMCAXRender::LightManager