I have the following 3D object:
The material of my 3D object is coded like this with 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);
}
The above code gives the same colors to 3D object entity uniformly. How can I give different colors to different sections of my entity? I want to highlight some section on my 3D object, is there a way to do that with Qt3D?
If it isn't possible with Qt3D, what is the best practice to do it with OpenGL?
I found a discussion which I feel like it would be very helpful.
After doing some research, the best approach might be to use OpenGL shading language or GLSL. I'm not sure.
With the great help of @AdaRaider I managed to implement a custom effect with modifiable vertex shader and fragment shader. Custom effect can be used like this:
Custom effect header is:
The implementation of custom effect is with two versions of OpenGL in mind, OpenGL ES 2.0 and OpenGL 3.1:
When I copy Phong shader default code inside my
custom-shader.vert
andcustom-shader.frag
files, it works exactly like Phong material, which shows the custom effect works fine.Now that the above custom effect is implemented, its shaders can be modified by the methods described by @AdaRaider to produce any desired effect.
In Qt I would imagine they are using "materials" as an abstraction of their predefined shaders. You create a material such as QPhongMaterial that you want to render an entity with and set things for that material which will be passed in as arguments to the shader (uniforms) like the ambient, specular and diffuse lighting color.
So you need a shader that will support vertex colors for your model. So each vertex of your model will have a color associated with it and these values get passed in to the vertex shader and forwarded to the fragment shader. It's fairly straightforward to do this with OpenGL but you're using Qt3D so it might be easier to use the infrastructure that's already there.
Qt3D already has some material classes that you can use to create some of these shaders to apply to your entity. You could try using the QPerVertexColorMaterial instead.
https://doc.qt.io/qt-5/qt3dextras-qpervertexcolormaterial.html
Obviously you will need to provide the list of vertex colors in order to color parts of the model differently. In addition to this, you will need to provide vertex colors for each vertex, even if you want to color each vertex of the triangle all the same color (face colors).
Alternatively you could create your own shader and give it to Qt3D to bind to the pipeline: (from the forum)
For custom materials the following example look promising: https://doc.qt.io/qt-5/qt3d-simplecustommaterial-example.html
And for information on Qt3D shaders: https://doc.qt.io/qt-5/qml-qt3d-render-shaderprogram.html
If you've never written a shader in GLSL and compiled it in an OpenGL program you might want to first get up to speed on how that is done as you need to understand the parts that the vertex, geometry and fragment shaders all play as well as the role of attributes and uniforms. I suppose you could still get the job done without doing that but I would imagine it would be significantly harder.
There is pages and pages out there on shaders but just briefly...
A shader generally comprises of three parts; the vertex shader, the geometry shader and the fragment shader, these are written using GLSL and usually saved as three files. At a minimum to compile a shader you need the vertex shader source and the fragment shader source.
Generally people like to save these files with the respective extension such as .frag, .vert or .vs/ .fs but ultimately they are just text files. To compile a shader and bind it to the render pipeline you need to load the source from the respective files and link them to create your shader program which you can then use by binding it to the render pipeline and rendering your geometry. Lazy Foo has an awesome tutorial on how that is done in OpenGL: http://lazyfoo.net/tutorials/SDL/51_SDL_and_modern_opengl/index.php
If you were just using OpenGL, you would first write a vertex shader then a fragment shader with the correct inputs/outputs for rendering geometry with vertex colors, then you would go through that process to create your shader program.
As for the shader implementation itself, here is a quick implementation of what your vertex and fragment shader would look like:
Vertex Shader (Color.vs)
Fragment Shader (Color.fs)