Hun*_*der 14 geometry opengl-es opengl-es-2.0
我想绘制一个球体,我知道如何使用glBegin()和glEnd()之类的调用在OpenGL中完成它.
但ES中没有任何内容.
建议/教程链接?
Bra*_*son 47
既然你已经使用OpenGL ES 2.0对其进行了标记,那么让我建议一种创建平滑球体的替代方法,那就是将它们绘制为光线追踪冒名顶替者.您不必计算复制光滑球体所需的许多顶点,而是可以利用球体从任何角度看起来几乎相同的事实.
为此,您需要使用以下过程:

您将表示两个三角形的四个顶点发送到顶点着色器,然后将它们移位以创建始终面向用户的正方形.在该正方形内,您可以使用片段着色器在每个像素上进行光栅渲染,并提供球体在该点处通过此方形窗口查看时所具有的颜色.
这种方法的优点是球体与显示器的分辨率一样平滑,球体很容易从小到大,无需重新计算几何体.它确实将渲染的负担从顶点处理器转移到片段处理器,但是对于单个球体来说,在我使用的OpenGL ES 2.0设备上并没有太大的问题.
我在这个iOS应用程序中使用了这种技术,在该页面上可以找到源代码,并在此处再讨论一下.我使用的顶点着色器的简化版本看起来像这样:
attribute vec4 position;
attribute vec4 inputImpostorSpaceCoordinate;
varying mediump vec2 impostorSpaceCoordinate;
varying mediump vec3 normalizedViewCoordinate;
uniform mat4 modelViewProjMatrix;
uniform mediump mat4 orthographicMatrix;
uniform mediump float sphereRadius;
void main()
{
vec4 transformedPosition;
transformedPosition = modelViewProjMatrix * position;
impostorSpaceCoordinate = inputImpostorSpaceCoordinate.xy;
transformedPosition.xy = transformedPosition.xy + inputImpostorSpaceCoordinate.xy * vec2(sphereRadius);
transformedPosition = transformedPosition * orthographicMatrix;
normalizedViewCoordinate = (transformedPosition.xyz + 1.0) / 2.0;
gl_Position = transformedPosition;
}
Run Code Online (Sandbox Code Playgroud)
和简化的片段着色器是这样的:
precision mediump float;
uniform vec3 lightPosition;
uniform vec3 sphereColor;
uniform mediump float sphereRadius;
uniform sampler2D depthTexture;
varying mediump vec2 impostorSpaceCoordinate;
varying mediump vec3 normalizedViewCoordinate;
const mediump vec3 oneVector = vec3(1.0, 1.0, 1.0);
void main()
{
float distanceFromCenter = length(impostorSpaceCoordinate);
// Establish the visual bounds of the sphere
if (distanceFromCenter > 1.0)
{
discard;
}
float normalizedDepth = sqrt(1.0 - distanceFromCenter * distanceFromCenter);
// Current depth
float depthOfFragment = sphereRadius * 0.5 * normalizedDepth;
// float currentDepthValue = normalizedViewCoordinate.z - depthOfFragment - 0.0025;
float currentDepthValue = (normalizedViewCoordinate.z - depthOfFragment - 0.0025);
// Calculate the lighting normal for the sphere
vec3 normal = vec3(impostorSpaceCoordinate, normalizedDepth);
vec3 finalSphereColor = sphereColor;
// ambient
float lightingIntensity = 0.3 + 0.7 * clamp(dot(lightPosition, normal), 0.0, 1.0);
finalSphereColor *= lightingIntensity;
// Per fragment specular lighting
lightingIntensity = clamp(dot(lightPosition, normal), 0.0, 1.0);
lightingIntensity = pow(lightingIntensity, 60.0);
finalSphereColor += vec3(0.4, 0.4, 0.4) * lightingIntensity;
gl_FragColor = vec4(finalSphereColor, 1.0);
}
Run Code Online (Sandbox Code Playgroud)
这些着色器的当前优化版本有点难以理解,我也使用环境遮挡照明,这些并不存在.还未示出该球体的纹理化,其可以通过适当的映射函数来完成,以在球体表面坐标和矩形纹理之间进行转换.这就是我为球体表面提供预先计算的环境遮挡值的方法.