opengl - 如何使一个部分的颜色在 3D 对象上不同

标签 opengl qt3d

我有以下 3D 对象:

tea pot

我的 3D 对象的 Material 使用 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。我不确定。

最佳答案

在 Qt 中,我想他们正在使用“ Material ”作为其预定义着色器的抽象。您创建一个 Material ,例如 QPhongMaterial,您希望使用它来渲染实体,并为该 Material 设置一些东西,这些东西将作为参数传递给着色器(制服),例如环境光、镜面反射和漫反射照明颜色。

因此,您需要一个支持模型顶点颜色的着色器。所以模型的每个顶点都会有一个与之关联的颜色,这些值会传递到顶点着色器并转发到片段着色器。使用 OpenGL 执行此操作相当简单,但您使用的是 Qt3D,因此使用已有的基础结构可能更容易。

Qt3D 已经有一些 Material 类,您可以使用它们来创建其中一些着色器以应用于您的实体。您可以尝试改用 QPerVertexColorMaterial。

https://doc.qt.io/qt-5/qt3dextras-qpervertexcolormaterial.html

Qt3DExtras::QPerVertexColorMaterial Default implementation for rendering the color properties set for each vertex

显然,您需要提供顶点颜色列表,以便对模型的各个部分进行不同的着色。除此之外,您还需要为每个顶点提供顶点颜色,即使您想为三角形的每个顶点都涂上相同的颜色(面颜色)。

或者,您可以创建自己的着色器并将其提供给 Qt3D 以绑定(bind)到管道: (来自论坛)

Qt3D does not generate shaders at runtime. For its default pipeline it comes with predefined default shaders. But you are free to change the pipeline as you wish (in C++ and also in QML) and you can use your own shaders.

对于自定义 Material ,以下示例看起来很有希望: https://doc.qt.io/qt-5/qt3d-simplecustommaterial-example.html

有关 Qt3D 着色器的信息: https://doc.qt.io/qt-5/qml-qt3d-render-shaderprogram.html

ShaderProgram class encapsulates a shader program. A shader program consists of several different shaders, such as vertex and fragment shaders. Qt3D will automatically populate a set of default uniforms if they are encountered during the shader instrospection phase.

如果您从未在 GLSL 中编写过着色器并在 OpenGL 程序中编译过它,您可能希望首先了解它是如何完成的,因为您需要了解顶点、几何和片段着色器所有的部分发挥以及属性和制服的作用。我想你仍然可以在不这样做的情况下完成工作,但我想这会更加困难。

着色器上有页面和页面,但只是短暂...

着色器通常由三部分组成;顶点着色器、几何着色器和片段着色器,这些是使用 GLSL 编写的,通常保存为三个文件。至少要编译着色器,您需要顶点着色器源代码和片段着色器源代码。

通常人们喜欢用相应的扩展名保存这些文件,例如 .frag、.vert 或 .vs/.fs,但最终它们只是文本文件。 要编译着色器并将其绑定(bind)到渲染管道,您需要从相应文件加载源代码并链接它们以创建您的着色器程序,然后您可以通过将其绑定(bind)到渲染管道并渲染几何图形来使用该着色器程序。 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;
}

关于opengl - 如何使一个部分的颜色在 3D 对象上不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52836013/

相关文章:

c++ - 禁用 Qt 3d 中的所有光源

c++ - 将 Qt3D 用于巨大的地形模型?

opengl - glsl 像素着色器 - 到最近目标像素的距离

c++ - glCreateShader失败并返回0

c++ - 使用 SFML 和 OpenGL 显示白色三角形?

qt - 将 qml 项添加到 Qt3DQuickWindow

c++ - Qt3d:应用 Qt3DRender::QLayerFilter 时显示的工件

python - OpenGL 基础 : calling glDrawElements once per object

c++ - 使用无屏幕创建 OpenGL 上下文