绘制在OpenGL ES球体绘制在OpenGL ES球体(Drawing a sphere in O

2019-05-13 22:21发布

我想画一个球,我知道如何使用电话,如在glBegin()和glEnd()做它在OpenGL。

但有没有在ES。

建议/教程链接?

Answer 1:

既然你已经标记这与OpenGL ES 2.0的,让我提出创建光滑球体的另一种方法,这是吸引他们的光线追踪骗子。 而不是计算你需要复制一个平稳领域的许多顶点,你可以采取的事实,即一个球体看起来非常从任何角度相同的优势。

要做到这一点,你使用类似如下的过程:

您发送四个顶点代表两个三角形的顶点着色器,然后取代他们创建总是面向用户的正方形。 在这一方,可以使用一个片段着色器在光栅的每个像素,并提供了一个球本来在这一点上,如果你是通过这种方窗观察它的颜色。

这种方法的优点是,你的显示器的分辨率支持,以及球会很容易从小到大的规模,而不需要您的几何体的任何重新计算领域是一样光滑。 它确实却将负担从顶点处理器片段处理器的渲染,但是对于单球体没有太多关于我曾经使用过的OpenGL ES 2.0的设备的问题。

我用这个技术, 这个iPhone应用程序 ,其源代码都可以在该网页上,并多一点谈论它在这里 。 顶点着色器我用的简化版本看起来是这样的:

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;
}

和简化的片段着色器是这样的:

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);
}

这些着色器的当前优化版本是有点难以跟随,并且我也使用环境闭塞照明,这是不存在这些问题。 也未示出是这样的球体,其可以用适当的映射函数来完成到球体表面的坐标和矩形纹理之间进行转换的纹理化。 这是我为我的球的表面提供预先计算的环境遮挡值。



文章来源: Drawing a sphere in OpenGL ES