qt - 具有统一 vec3 数组的 Qt3D 着色器图
问题描述
更新
因此,通过打印编译后的着色器代码,QShaderProgramBuilder
我发现着色器几乎可以工作,唯一的问题是调用renderClicks
. 这条线
fragColor = (((renderClicks(clicks[10], colors[10], (((((((phongFunction(ka, kd, ks, shininess, worldPosition, normalize(((eyePosition - worldPosition))), normalize(worldNormal)))))))))))));
应该是这样的
fragColor = (((renderClicks(clicks, colors, (((((((phongFunction(ka, kd, ks, shininess, worldPosition, normalize(((eyePosition - worldPosition))), normalize(worldNormal)))))))))))));
但由于制服的名称是clicks[10]
,colors[10]
我不确定这是否可以修复。
问题
我QSceneLoader
在我的项目中使用自动加载对象。现在我想可视化对象 3D 表面上的点击。为此,我正在遍历场景加载器创建的实体层次结构,直到到达QShaderProgramBuilder
. 接下来,我将替换着色器程序构建器中的片段着色器图setFragmentShaderGraph
- 不幸的是,您无法提供包含普通着色器代码的文本文件。
我使用来自 GitHub 的默认 phong 图作为起点,并添加了我自己的制服——点击次数和点击次数的颜色,都是vec3
数组。不幸的是,在我从两者中删除数组定义之前,着色器无法工作。
当我从任何地方删除数组定义(即vec3 clicks
代替vec3 clicks[10]
)并传递 aQVector3D
而不是 a 时,QVector<QVector3D>
我得到了渲染的正常场景。
我也找不到这里提到的 Qt3D 节点编辑器,但我怀疑它能否解决我的问题,因为在 YouTube 上的视频中似乎没有任何选项可以声明数组。
那么,有什么想法可以在着色器图中正确使用统一数组吗?
注意:我已经检查了 4.6 的 OpenGL 版本,所以这不应该是问题。
注 2:如果有人需要示例项目,请告诉我。我开始创建一个,但即使我试图保持它很小,它也变得相当大。它还没有完成,但我可以完成它并将其上传到 GitHub。
编码
这是我从 C++ 提供数据作为参数的方式:
Qt3DRender::QParameter *clicksParameter = new Qt3DRender::QParameter(QStringLiteral("clicks"), m_clicks.constData());
我更改了着色器图以包含以下新内容prototype
:
"prototypes": {
"renderClicks": {
"inputs": ["clicks[10]", "colors[10]", "currentColor"],
"outputs": ["result"],
"parameters": {
"type": {
"type": "QShaderLanguage::VariableType",
"value": "QShaderLanguage::Vec4"
}
},
"rules": [{
"format": {
"api": "OpenGLCoreProfile",
"major": 3,
"minor": 0
},
"headerSnippets": [
"#pragma include :shaders/poseeditor/clicksRendering.inc.frag"
],
"substitution": "vec4 $result = renderClicks($clicks, $colors, $currentColor);"
}]
}
},
"nodes": ...
其中引用了以下着色器代码clicksRendering.inc.frag
:
vec4 renderClicks(vec3 clicks[10], vec3 colors[10], vec4 currentColor) {
return currentColor;
}
然后我添加了以下新内容nodes
:
...
{
"uuid": "{00000000-0000-0000-0000-000000000026}",
"type": "input",
"parameters": {
"name": "clicks[10]",
"qualifier": {
"type": "QShaderLanguage::StorageQualifier",
"value": "QShaderLanguage::Uniform"
},
"type": {
"type": "QShaderLanguage::VariableType",
"value": "QShaderLanguage::Vec3"
}
}
},
{
"uuid": "{00000000-0000-0000-0000-000000000027}",
"type": "input",
"parameters": {
"name": "colors[10]",
"qualifier": {
"type": "QShaderLanguage::StorageQualifier",
"value": "QShaderLanguage::Uniform"
},
"type": {
"type": "QShaderLanguage::VariableType",
"value": "QShaderLanguage::Vec3"
}
}
},
{
"uuid": "{00000000-0000-0000-0000-000000000028}",
"type": "renderClicks"
},
...
我还更改了最后的边缘,以便最终的 phong 颜色通过我的自定义函数传递:
...
{
"sourceUuid": "{00000000-0000-0000-0000-000000000026}",
"sourcePort": "value",
"targetUuid": "{00000000-0000-0000-0000-000000000028}",
"targetPort": "clicks"
},
{
"sourceUuid": "{00000000-0000-0000-0000-000000000027}",
"sourcePort": "value",
"targetUuid": "{00000000-0000-0000-0000-000000000028}",
"targetPort": "colors"
},
{
"sourceUuid": "{00000000-0000-0000-0000-000000000024}",
"sourcePort": "outputColor",
"targetUuid": "{00000000-0000-0000-0000-000000000028}",
"targetPort": "currentColor"
},
{
"sourceUuid": "{00000000-0000-0000-0000-000000000028}",
"sourcePort": "result",
"targetUuid": "{00000000-0000-0000-0000-000000000025}",
"targetPort": "fragColor"
}
...
附加信息
我试图[10]
从新inputs
的prototype
. 这会输出一个错误和错误的着色器代码:
const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0;
const int TYPE_DIRECTIONAL = 1;
const int TYPE_SPOT = 2;
struct Light {
int type;
vec3 position;
vec3 color;
float intensity;
vec3 direction;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
float cutOffAngle;
};
uniform Light lights[MAX_LIGHTS];
uniform int lightCount;
// Pre-convolved environment maps
struct EnvironmentLight {
samplerCube irradiance; // For diffuse contribution
samplerCube specular; // For specular contribution
};
uniform EnvironmentLight envLight;
uniform int envLightCount = 0;
#line 52
void adsModel(const in vec3 worldPos,
const in vec3 worldNormal,
const in vec3 worldView,
const in float shininess,
out vec3 diffuseColor,
out vec3 specularColor)
{
diffuseColor = vec3(0.0);
specularColor = vec3(0.0);
// We perform all work in world space
vec3 n = normalize(worldNormal);
vec3 s = vec3(0.0);
for (int i = 0; i < lightCount; ++i) {
float att = 1.0;
float sDotN = 0.0;
if (lights[i].type != TYPE_DIRECTIONAL) {
// Point and Spot lights
// Light position is already in world space
vec3 sUnnormalized = lights[i].position - worldPos;
s = normalize(sUnnormalized); // Light direction
// Calculate the attenuation factor
sDotN = dot(s, n);
if (sDotN > 0.0) {
if (lights[i].constantAttenuation != 0.0
|| lights[i].linearAttenuation != 0.0
|| lights[i].quadraticAttenuation != 0.0) {
float dist = length(sUnnormalized);
att = 1.0 / (lights[i].constantAttenuation +
lights[i].linearAttenuation * dist +
lights[i].quadraticAttenuation * dist * dist);
}
// The light direction is in world space already
if (lights[i].type == TYPE_SPOT) {
// Check if fragment is inside or outside of the spot light cone
if (degrees(acos(dot(-s, lights[i].direction))) > lights[i].cutOffAngle)
sDotN = 0.0;
}
}
} else {
// Directional lights
// The light direction is in world space already
s = normalize(-lights[i].direction);
sDotN = dot(s, n);
}
// Calculate the diffuse factor
float diffuse = max(sDotN, 0.0);
// Calculate the specular factor
float specular = 0.0;
if (diffuse > 0.0 && shininess > 0.0) {
float normFactor = (shininess + 2.0) / 2.0;
vec3 r = reflect(-s, n); // Reflection direction in world space
specular = normFactor * pow(max(dot(r, worldView), 0.0), shininess);
}
// Accumulate the diffuse and specular contributions
diffuseColor += att * lights[i].intensity * diffuse * lights[i].color;
specularColor += att * lights[i].intensity * specular * lights[i].color;
}
}
vec4 phongFunction(const in vec4 ambient,
const in vec4 diffuse,
const in vec4 specular,
const in float shininess,
const in vec3 worldPosition,
const in vec3 worldView,
const in vec3 worldNormal)
{
// Calculate the lighting model, keeping the specular component separate
vec3 diffuseColor, specularColor;
adsModel(worldPosition, worldNormal, worldView, shininess, diffuseColor, specularColor);
// Combine spec with ambient+diffuse for final fragment color
vec3 color = (ambient.rgb + diffuseColor) * diffuse.rgb
+ specularColor * specular.rgb;
return vec4(color, diffuse.a);
}
#line 11
uniform vec3 clicks[10];
uniform vec3 colors[10];
vec4 renderClicks(vec3 clicks[10], vec3 colors[10], vec4 currentColor) {
return currentColor;
}
#line 15
out vec4 fragColor;
void main()
{
fragColor = (((renderClicks(clicks[10], colors[10], (((((((phongFunction(ka, kd, ks, shininess, worldPosition, normalize(((eyePosition - worldPosition))), normalize(worldNormal)))))))))))));
}
所以着色器看起来不错,除了调用renderClicks(clicks[10], colors[10], ...)
. 但我不知道我是否可以摆脱这些[10]
部分,因为那是他们的名字。
解决方案
推荐阅读
- python - 如何编写代码来识别发生移位的索引并从python中的另一个数组中获取相应的值?
- canvas - 在鼠标拖动时调整矩形大小的正确算法
- python - 将时间戳舍入到微秒 - 熊猫
- android - 如何从 Android 上不可绘制的图像中选择主色
- javascript - (节点:2256)UnhandledPromiseRejectionWarning:未处理的承诺拒绝
- sql - 如何限制选择与选择
- angular - Angular - 如何在 Angular 9 - Ivy 中进行代码拆分?
- python - 有没有办法让 for 循环在同一行打印下划线而不是在彼此下方?
- android - AWS Amplify Modlegen 生成 Android Studio 编译错误
- python - cv2.VideoCapture 冻结了我的整个计算机