【发布时间】:2018-09-06 19:12:00
【问题描述】:
我正在创建一个 UV 球体(类似于划分为纬度线的地球球)。我这样做是:
- 计算每个平行纬度圆周围的所有顶点(例如,每个圆 72 个点)
- 使用 GL_TRIANGLE_STRIP 填充每个纬度圈之间的每个“切片”。
不幸的是,我一直在我原本完美的球体上看到点。
什么会导致这种情况,我该如何摆脱它?
void CSphere2::AddVertices( void )
{
#define SPHERE2_RES 72
// Create sphere using horizontal slices/circles
int nPointsPerCircle = SPHERE2_RES;
int nStackedCircles = SPHERE2_RES;
GLfloat r = m_Size;
GLfloat yAngle = - (PI / 2.0f); // Start at -90deg and work up to +90deg (south to north pole)
GLfloat yAngleStep = PI / nStackedCircles;
// Sweep angle is zero initially for pointing towards me (-Z direction)
GLfloat horizSweepAngle = 0;
GLfloat horizSweepStep = ( 2 * PI ) / nPointsPerCircle;
// Each time we have a slice, the top and bottom radii vary..
GLfloat sweepRadiusTop;
GLfloat sweepRadiusBottom;
GLfloat xBottomPoint;
GLfloat zBottomPoint;
GLfloat xTopPoint;
GLfloat zTopPoint;
for( int c = 0; c < nStackedCircles; c ++ )
{
// Draw a circle - note that this always uses two circles - a top and bottom circle.
GLfloat yBottomCircle;
GLfloat yTopCircle;
yTopCircle = r * sin( yAngle + yAngleStep );
yBottomCircle = r * sin( yAngle );
std::vector<GLfloat> vBottom_x;
std::vector<GLfloat> vBottom_z;
std::vector<GLfloat> vTop_x;
std::vector<GLfloat> vTop_z;
sweepRadiusTop = r * cos( yAngle + yAngleStep );
sweepRadiusBottom = r * cos( yAngle );
// Add 1 face - a triangle strip per slice..
AddFace();
m_Faces[ c ].m_DrawType = GL_TRIANGLE_STRIP;
// Now work out the position of the points around each circle - bottom points will always be the
// same as the last top circle points.. but I'm not going to try optimising yet..
for( int s = 0; s < nPointsPerCircle; s ++ )
{
GLfloat xBottomPoint = sweepRadiusBottom * sin( horizSweepAngle );
GLfloat zBottomPoint = sweepRadiusBottom * cos( horizSweepAngle );
GLfloat xTopPoint = sweepRadiusTop * sin( horizSweepAngle + horizSweepStep );
GLfloat zTopPoint = sweepRadiusTop * cos( horizSweepAngle + horizSweepStep );
vBottom_x.push_back( xBottomPoint );
vBottom_z.push_back( zBottomPoint );
vTop_x.push_back( xTopPoint );
vTop_z.push_back( zTopPoint );
horizSweepAngle += horizSweepStep;
}
// OPTIMISE THIS!!
for( int s = 1; s <= nPointsPerCircle + 1; s ++ )
{
if( s == nPointsPerCircle + 1 )
{
// Join the last bottom point with the very first top point - go one more to fully close and leave no vertical gap
xTopPoint = vTop_x[ 1 ];
zTopPoint = vTop_z[ 1 ];
xBottomPoint = vBottom_x[ 0 ];
zBottomPoint = vBottom_z[ 0 ];
}
else
if( s == nPointsPerCircle )
{
// Join the last bottom point with the very first top point
xTopPoint = vTop_x[ 0 ];
zTopPoint = vTop_z[ 0 ];
xBottomPoint = vBottom_x[ s - 1 ];
zBottomPoint = vBottom_z[ s - 1 ];
}
else
{
xTopPoint = vTop_x[ s ];
zTopPoint = vTop_z[ s ];
xBottomPoint = vBottom_x[ s - 1 ];
zBottomPoint = vBottom_z[ s - 1 ];
}
// Calculate and add the Normal for each vertex.. Normal for a point on surface of a Sphere2 should be the unit vector going from centre
// of the Sphere2 to the surface (x,y,z).
//
// If centre of Sphere2 is 0,0,0 then N = | {x,y,z} - {0,0,0} | = | {x,y,z} |
glm::vec3 vNormalBottom = glm::vec3( xBottomPoint, yBottomCircle, zBottomPoint );
vNormalBottom = glm::normalize( vNormalBottom );
glm::vec3 vNormalTop = glm::vec3( xTopPoint, yTopCircle, zTopPoint );
vNormalTop = glm::normalize( vNormalTop );
// Add bottom of slice vertex..
m_Faces[ c ].AddVertexWithNormal( xBottomPoint, yBottomCircle, zBottomPoint, vNormalBottom.x, vNormalBottom.y, vNormalBottom.z );
// Add top of slice vertex, next step position..
m_Faces[ c ].AddVertexWithNormal( xTopPoint, yTopCircle, zTopPoint, vNormalTop.x, vNormalTop.y, vNormalTop.z );
}
int nVertexCount = m_Faces[ c ].m_Vertices.size();
m_Faces[ c ].m_SideCount = nVertexCount;
// Face colouring colours the vertices so they need to be created first..
m_Faces[ c ].SetRGB( m_RGBA.r, m_RGBA.g, m_RGBA.b );
yAngle += yAngleStep;
}
}
void CSphere2::Create( GLfloat fSize )
{
m_Size = fSize;
// Must add vertices first..
AddVertices();
glGenBuffers( 1, &m_VBO );
glBindBuffer( GL_ARRAY_BUFFER, m_VBO );
int nFaces = m_Faces.size();
int nVertexCount = 0;
for( int f = 0; f < nFaces; f ++ )
{
nVertexCount += m_Faces[ f ].m_Vertices.size();
m_Faces[ f ].m_SideCount = nVertexCount;
}
// Define the size of the buffer..
glBufferData( GL_ARRAY_BUFFER, sizeof( COLVERTEX ) * nVertexCount, NULL, GL_STATIC_DRAW );
int nOffset = 0;
for( int f = 0; f < nFaces; f ++ )
{
// Copy in each vertice's data..
for( int v = 0; v < (int) m_Faces[ f ].m_Vertices.size(); v ++ )
{
glBufferSubData( GL_ARRAY_BUFFER, nOffset, sizeof( COLVERTEX ), &m_Faces[ f ].m_Vertices[ v ].m_VertexData );
nOffset += sizeof( COLVERTEX );
}
}
glBindBuffer( GL_ARRAY_BUFFER, 0 );
}
我从其他地方复制的其他示例也遇到了同样的问题,所以我坐下来自己计算了一下,但我仍然遇到同样的问题。
顶点着色器:
char *vs3DShader =
"#version 140\n"
"#extension GL_ARB_explicit_attrib_location : enable\n"
"layout (location = 0) in vec3 Position;"
"layout (location = 1) in vec4 color;"
"layout (location = 2) in vec3 aNormal;"
"out vec4 frag_color;"
"out vec3 Normal;"
"out vec3 FragPos;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main()"
"{"
" FragPos = vec3(model * vec4(Position, 1.0));"
" gl_Position = projection * view * vec4(FragPos, 1.0);"
// Rotate normals with respect to current Model matrix (object rotation).
" Normal = mat3( transpose( inverse( model ) ) ) * aNormal; "
" // Pass vertex color to fragment shader.. \n"
" frag_color = color;"
"}"
;
片段着色器:
char *fs3DShader =
"#version 140\n"
"in vec4 frag_color;"
"in vec3 Normal;"
"in vec3 FragPos;"
"out vec4 FragColor;"
"uniform vec3 lightPos; "
"uniform vec3 lightColor; "
"void main()"
"{"
" // ambient\n"
" float ambientStrength = 0.1;"
" vec3 ambient = ambientStrength * lightColor;"
" // diffuse \n"
" vec3 norm = normalize(Normal);"
" vec3 lightDir = normalize(lightPos - FragPos);"
" float diff = max(dot(norm, lightDir), 0.0);"
" vec3 diffuse = diff * lightColor;"
" vec3 result = (ambient + diffuse) * frag_color;"
" FragColor = vec4(result, 1.0);"
"}"
;
我是否缺少某种平滑选项?我尝试将我的视点移动到球体的两侧,并且点都在周围发生 - 所以问题不是三角形条带“关闭”的地方 - 它遍布整个球体。
请看下面的亮点:
更新:我只是想证明回绕到零度不是问题。下面是每个圆圈只有四分之一被扫过 90 度时的图像。点仍然出现在中间区域。
【问题讨论】:
标签: c++ opengl opengl-es-2.0 fragment-shader vertex-shader