我有以下3D对象:
我的3D对象的材质使用Qt3D进行了这样的编码:
void MyClass::addMaterial(Qt3DCore::QEntity *entity)
{
Qt3DExtras::QPhongMaterial * material = new Qt3DExtras::QPhongMaterial();
material->setAmbient(QColor(245-30, 245-15, 245));
material->setDiffuse(QColor(125-30, 125-15, 125));
material->setSpecular(QColor(215-30, 255-15, 255));
entity->addComponent(material);
}
上面的代码为3D对象实体统一赋予了相同的颜色。如何为实体的不同部分赋予不同的颜色?我想在我的3D对象上突出显示某些部分,是否可以使用Qt3D做到这一点?
如果Qt3D无法实现,那么 OpenGL 的最佳实践是什么?
我发现了一个discussion,我觉得这会很有帮助。
经过研究,最好的方法可能是使用OpenGL阴影语言或 GLSL 。我不确定。
答案 0 :(得分:3)
在Qt中,我可以想象他们使用“材质”作为其预定义着色器的抽象。您创建了诸如QPhongMaterial这样的材质,您要使用该材质渲染实体并为其设置东西,这些东西将作为参数传递给着色器(均匀),例如环境,镜面反射和漫射照明颜色。
因此,您需要一个支持模型顶点颜色的着色器。因此,模型的每个顶点都将具有与之关联的颜色,并且这些值将传递到顶点着色器中并转发到片段着色器。使用OpenGL进行操作相当简单,但是您正在使用Qt3D,因此使用现有的基础结构可能会更容易。
Qt3D已经具有一些材质类,可用于创建其中一些着色器以应用于您的实体。您可以尝试改用QPerVertexColorMaterial。
https://doc.qt.io/qt-5/qt3dextras-qpervertexcolormaterial.html
Qt3DExtras :: QPerVertexColorMaterial的默认实现 渲染为每个顶点设置的颜色属性
很显然,您需要提供顶点颜色列表,以便对模型的各个部分进行不同的着色。除此之外,即使您要为三角形的每个顶点都上色相同的颜色(面色),也需要为每个顶点提供顶点颜色。
或者,您可以创建自己的着色器并将其提供给Qt3D以绑定到管道: (来自论坛)
Qt3D在运行时不会生成着色器。对于其默认管道,它带有预定义的默认着色器。但是,您可以随意更改管道(在C ++和QML中),并且可以使用自己的着色器。
对于定制材料,以下示例看起来很有希望: https://doc.qt.io/qt-5/qt3d-simplecustommaterial-example.html
有关Qt3D着色器的信息: https://doc.qt.io/qt-5/qml-qt3d-render-shaderprogram.html
ShaderProgram类封装了着色器程序。着色器程序由几个不同的着色器组成,例如顶点和片段着色器。 如果在着色器自省阶段遇到默认制服,则Qt3D将自动填充一组默认制服。
如果您从未用GLSL编写着色器并在OpenGL程序中对其进行编译,则可能需要首先了解如何完成顶点,几何和片段着色器的所有部分,以加快其完成速度以及属性和制服的作用。我想您仍然可以不做而完成工作,但我想这会困难得多。
着色器上有很多页面,但是只是短暂的...
着色器通常包括三个部分;顶点着色器,几何着色器和片段着色器是使用GLSL编写的,通常保存为三个文件。至少要编译着色器,您需要顶点着色器源和片段着色器源。
通常,人们喜欢使用相应的扩展名(例如.frag,.vert或.vs / .fs)保存这些文件,但最终它们只是文本文件。 要编译着色器并将其绑定到渲染管道,您需要从相应文件加载源并将其链接以创建着色器程序,然后将其绑定到渲染管道并渲染几何图形即可使用。 Lazy Foo有一个很棒的教程,介绍了如何在OpenGL中完成该操作:http://lazyfoo.net/tutorials/SDL/51_SDL_and_modern_opengl/index.php
如果仅使用OpenGL,则首先要编写一个顶点着色器,然后编写一个具有正确输入/输出的片段着色器,以渲染具有顶点颜色的几何图形,然后完成该过程以创建着色器程序。
对于着色器实现本身,这是顶点和片段着色器的外观的快速实现:
顶点着色器(Color.vs)
#version 330
in vec3 position;
in vec4 vertexColor;
uniform mat4 WORLD_VIEW_PROJECTION_MATRIX;
out vec4 fragColor;
void main()
{
fragColor.x = vertexColor.x;
fragColor.y = vertexColor.y;
fragColor.z = vertexColor.z;
fragColor.w = vertexColor.w; //alpha
gl_Position = WORLD_VIEW_PROJECTION_MATRIX * vec4( position, 1 );
}
片段着色器(Color.fs)
#version 330
out vec4 LFragment;
in vec4 fragColor;
void main()
{
LFragment = fragColor;
}
答案 1 :(得分:1)
在@AdaRaider的大力帮助下,我成功实现了具有可修改的顶点着色器和片段着色器的自定义效果。自定义效果可以这样使用:
#include "customeffect.h"
static const QColor ambientColor("#576675"); // Shader input
static const QColor diffuseColor("#5F6E7D"); // Shader input
static const QColor SpecularColor("#61707F"); // Shader input
static const float shininess(0.0); // Shader input
void MyClass::addMaterial(Qt3DCore::QEntity *entity)
{
Qt3DRender::QMaterial * material = new Qt3DRender::QMaterial();
material->setEffect(new CustomEffect());
material->addParameter(new Qt3DRender::QParameter(QStringLiteral("ka"), ambientColor));
material->addParameter(new Qt3DRender::QParameter(QStringLiteral("kd"), diffuseColor));
material->addParameter(new Qt3DRender::QParameter(QStringLiteral("ks"), SpecularColor));
material->addParameter(new Qt3DRender::QParameter(QStringLiteral("shininess"), shininess));
entity->addComponent(material);
}
自定义效果标题为:
#ifndef CUSTOMEFFECT_H
#define CUSTOMEFFECT_H
#include <Qt3DRender/QEffect>
class CustomEffect : public Qt3DRender::QEffect
{
public:
explicit CustomEffect(Qt3DCore::QNode *parent = nullptr);
};
#endif // CUSTOMEFFECT_H
自定义效果的实现考虑了OpenGL的两个版本,即OpenGL ES 2.0 和OpenGL 3.1 :
#include "customeffect.h"
#include <Qt3DRender/QTechnique>
#include <Qt3DRender/QGraphicsApiFilter>
#include <QtCore/QUrl>
CustomEffect::CustomEffect(Qt3DCore::QNode *parent)
: Qt3DRender::QEffect(parent)
{
Qt3DRender::QTechnique *techniqueES20 = new Qt3DRender::QTechnique();
techniqueES20->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile);
techniqueES20->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGLES);
techniqueES20->graphicsApiFilter()->setMajorVersion(2);
techniqueES20->graphicsApiFilter()->setMinorVersion(0);
Qt3DRender::QTechnique *techniqueGL31 = new Qt3DRender::QTechnique();
techniqueGL31->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile);
techniqueGL31->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL);
techniqueGL31->graphicsApiFilter()->setMajorVersion(3);
techniqueGL31->graphicsApiFilter()->setMinorVersion(1);
Qt3DRender::QFilterKey *filterkey = new Qt3DRender::QFilterKey(this);
filterkey->setName(QStringLiteral("renderingStyle"));
filterkey->setValue(QStringLiteral("forward"));
techniqueES20->addFilterKey(filterkey);
techniqueGL31->addFilterKey(filterkey);
Qt3DRender::QShaderProgram *shader2 = new Qt3DRender::QShaderProgram();
shader2->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/qt3deditorlib/shaders/es2/custom-shader.vert"))));
shader2->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/qt3deditorlib/shaders/es2/custom-shader.frag"))));
Qt3DRender::QShaderProgram *shader3 = new Qt3DRender::QShaderProgram();
shader3->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/qt3deditorlib/shaders/gl3/custom-shader.vert"))));
shader3->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/qt3deditorlib/shaders/gl3/custom-shader.frag"))));
Qt3DRender::QRenderPass *renderPass2 = new Qt3DRender::QRenderPass();
renderPass2->setShaderProgram(shader2);
Qt3DRender::QRenderPass *renderPass3 = new Qt3DRender::QRenderPass();
renderPass3->setShaderProgram(shader3);
techniqueES20->addRenderPass(renderPass2);
techniqueGL31->addRenderPass(renderPass3);
addTechnique(techniqueES20);
addTechnique(techniqueGL31);
}
当我在custom-shader.vert
和custom-shader.frag
文件中复制Phong着色器默认代码时,它的工作原理与Phong材质完全一样,表明自定义效果很好。
现在已实现上述自定义效果,可以使用@AdaRaider描述的方法修改其着色器以产生任何所需的效果。