gpt4 book ai didi

optimization - 法线的 GLSL 着色器生成

转载 作者:行者123 更新时间:2023-12-03 16:51:56 30 4
gpt4 key购买 nike

您好,我正在编写 3D 建模应用程序,我想加快 OpenGL 中的渲染速度。目前我使用的是 glBegin/glEnd,这是一种非常缓慢且已弃用的方式。我需要绘制非常快速的平面阴影模型。我每一帧都在 CPU 上生成法线。这很慢。我尝试将 glDrawElements 与索引几何一起使用,但在法线生成中存在问题,因为法线是在顶点而非三角形级别指定的。
另一个想法是在几何着色器中使用 GLSL 在 GPU 上生成法线。我为正常生成编写了这段代码:

#version 120 
#extension GL_EXT_geometry_shader4 : enable

vec3 NormalFromTriangleVertices(vec3 triangleVertices[3])
{
// now is same as RedBook (OpenGL Programming Guide)
vec3 u = triangleVertices[0] - triangleVertices[1];
vec3 v = triangleVertices[1] - triangleVertices[2];
return cross(v, u);
}

void main()
{
// no change of position
// computes normal from input triangle and front color for that triangle

vec3 triangleVertices[3];
vec3 computedNormal;

vec3 normal, lightDir;
vec4 diffuse;
float NdotL;

vec4 finalColor;

for(int i = 0; i < gl_VerticesIn; i += 3)
{
for (int j = 0; j < 3; j++)
{
triangleVertices[j] = gl_PositionIn[i + j].xyz;
}
computedNormal = NormalFromTriangleVertices(triangleVertices);
normal = normalize(gl_NormalMatrix * computedNormal);

// hardcoded light direction
vec4 light = gl_ModelViewMatrix * vec4(0.0, 0.0, 1.0, 0.0);
lightDir = normalize(light.xyz);

NdotL = max(dot(normal, lightDir), 0.0);

// hardcoded
diffuse = vec4(0.5, 0.5, 0.9, 1.0);

finalColor = NdotL * diffuse;
finalColor.a = 1.0; // final color ignores everything, except lighting

for (int j = 0; j < 3; j++)
{
gl_FrontColor = finalColor;
gl_Position = gl_PositionIn[i + j];
EmitVertex();
}
}
EndPrimitive();
}

当我将着色器集成到我的应用程序中时,速度没有提高。情况比以前更糟。我是 GLSL 和着色器的新手,所以我不知道我做错了什么。我在配备 Geforce 9400M 的 MacBook 上试过这段代码。

更清楚地说,这是我要替换的代码:

- (void)drawAsCommandsWithScale:(Vector3D)scale
{
float frontDiffuse[4] = { 0.4, 0.4, 0.4, 1 };
CGFloat components[4];
[color getComponents:components];
float backDiffuse[4];
float selectedDiffuse[4] = { 1.0f, 0.0f, 0.0f, 1 };

for (uint i = 0; i < 4; i++)
backDiffuse[i] = components[i];

glMaterialfv(GL_BACK, GL_DIFFUSE, backDiffuse);
glMaterialfv(GL_FRONT, GL_DIFFUSE, frontDiffuse);

Vector3D triangleVertices[3];

float *lastDiffuse = frontDiffuse;

BOOL flip = scale.x < 0.0f || scale.y < 0.0f || scale.z < 0.0f;

glBegin(GL_TRIANGLES);

for (uint i = 0; i < triangles->size(); i++)
{
if (selectionMode == MeshSelectionModeTriangles)
{
if (selected->at(i))
{
if (lastDiffuse == frontDiffuse)
{
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, selectedDiffuse);
lastDiffuse = selectedDiffuse;
}
}
else if (lastDiffuse == selectedDiffuse)
{
glMaterialfv(GL_BACK, GL_DIFFUSE, backDiffuse);
glMaterialfv(GL_FRONT, GL_DIFFUSE, frontDiffuse);
lastDiffuse = frontDiffuse;
}
}
Triangle currentTriangle = [self triangleAtIndex:i];
if (flip)
currentTriangle = FlipTriangle(currentTriangle);

[self getTriangleVertices:triangleVertices fromTriangle:currentTriangle];
for (uint j = 0; j < 3; j++)
{
for (uint k = 0; k < 3; k++)
{
triangleVertices[j][k] *= scale[k];
}
}
Vector3D n = NormalFromTriangleVertices(triangleVertices);
n.Normalize();
for (uint j = 0; j < 3; j++)
{
glNormal3f(n.x, n.y, n.z);
glVertex3f(triangleVertices[j].x, triangleVertices[j].y, triangleVertices[j].z);
}
}

glEnd();
}

如您所见,它的效率非常低,但可以正常工作。trianglesvertices 数组中的索引数组。

我尝试使用此代码进行绘图,但我不能只有一个索引数组而不是两个(一个用于顶点,第二个用于法线)。

glEnableClientState(GL_VERTEX_ARRAY);

uint *trianglePtr = (uint *)(&(*triangles)[0]);
float *vertexPtr = (float *)(&(*vertices)[0]);

glVertexPointer(3, GL_FLOAT, 0, vertexPtr);
glDrawElements(GL_TRIANGLES, triangles->size() * 3, GL_UNSIGNED_INT, trianglePtr);
glDisableClientState(GL_VERTEX_ARRAY);

现在,当一些顶点由不同的三角形共享时,我如何指定指向法线的指针,所以它们的法线不同?

最佳答案

所以我终于设法提高了渲染速度。我在 CPU 上重新计算法线,仅当顶点或三角形发生变化时,这仅在一个网格而不是整个场景中工作时发生。这不是我想要的解决方案,但在现实世界中它比以前的方法更好。
我将整个几何缓存到单独的法线和顶点数组中,无法使用索引绘图,因为我想要平面着色(与 3ds max 中的平滑组类似的问题)。
我使用简单的 glDrawArrays 和照明顶点着色器,那是因为我想在三角形模式下为选定的三角形使用不同的颜色,为未选择的三角形使用另一种颜色并且没有 Material 阵列(我没有找到任何一个).

关于optimization - 法线的 GLSL 着色器生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1964308/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com