2012-05-07 4 views
13

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

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

Рекомендации/Ссылки на учебники?

+0

проверить этот вопрос вне - http://stackoverflow.com/questions/6072308/problem-drawing-a-sphere-in-opengl-es – alegen

+0

Как уже упоминалось в URL: http://www.learnopengles.com/ android-lesson-one-getting-started/ –

ответ

41

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

Чтобы сделать это, вы используете процесс, как следующее:

Sphere impostor generation

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

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

Я использую эту технику в this iOS application, для которой исходный код доступен на этой странице, и поговорите об этом чуть больше here. Упрощенная версия вершинных шейдеров я использую выглядит примерно так:

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

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

+0

Я тоже использовал рекламный щит http://williamedwardscoder.tumblr.com/post/13270747573/when-playing-with-game-engine-ideas-i-struggled; мой ключевой ввод заключается в том, что для достижения наилучших результатов вы должны нарисовать края во втором проходе.Я отказался от этой техники при переходе на OpenGLES 2/webGL, поскольку вы больше не можете установить глубину на фрагмент :( – Will

+0

Что такое 'орфографическая матрица' в вашем коде? Является ли она матрицей, которая превращает квадрат в лицо? –

+0

@ SzałPał - он предназначен для исправления не квадратной формы визуализации. –

0

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

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

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

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

Смежные вопросы