Подтвердить что ты не робот

Рисование сферы в OpenGL ES

Я хочу нарисовать сферу, я знаю, как это сделать в OpenGL, используя вызовы, такие как glBegin() и glEnd().

Но в ES ничего нет.

Ссылки на предложения/учебные материалы?

4b9b3361

Ответ 1

Поскольку вы отметили это с помощью OpenGL ES 2.0, позвольте мне предложить альтернативный подход для создания гладких сфер, а также для того, чтобы нарисовать их как raytraced impostors. Вместо того, чтобы вычислять множество вершин, которые вам нужны для репликации гладкой сферы, вы можете воспользоваться тем фактом, что сфера выглядит практически одинаково с любого угла.

Для этого вы используете следующий процесс:

Sphere impostor generation

Вы отправляете четыре вершины, представляющие два треугольника, в вершинный шейдер, который затем смещает их, чтобы создать квадрат, который всегда стоит перед пользователем. В пределах этой площади вы используете фрагментарный шейдер для растрового изображения по каждому пикселю и обеспечиваете цвет, который будет иметь сфера в этой точке, если бы вы просматривали его через это квадратное окно.

Преимущество этого подхода в том, что сфера настолько же плавная, как и разрешение вашего дисплея, и сфера будет легко масштабироваться от малого до большого, не требуя перерасчета вашей геометрии. Он переносит нагрузку на рендеринг с процессора вершины на процессор фрагмента, но для одной сферы, которая не является большой проблемой на устройствах 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;
}

и упрощенным шейдером фрагментов является следующее:

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

Текущим оптимизированным версиям этих шейдеров немного сложнее следовать, и я также использую освещение внешней окклюзии, которого нет у них. Также не показано текстурирование этой сферы, что можно сделать с помощью правильной функции отображения для перевода между поверхностными координатами сферы и прямоугольной текстурой. Вот как я предоставляю заранее рассчитанные значения окклюзии окружающей среды для поверхностей моих сфер.

Ответ 2

Люди, посещающие эту тему, могут посмотреть ссылку, приведенную ниже, для создания различных форм, включая "Сфера" в OpenGLES2.0.

https://github.com/regar007/ShapesInOpenGLES2.0

Внеклассная реализация форм позволяет легко интегрироваться с вашим кодом.

Создайте объект и используйте функцию рендеринга для рисования объекта.