2012-05-07 34 views
13

Quiero dibujar una esfera, sé cómo hacerlo en OpenGL usando llamadas como glBegin() & glEnd().Dibujando una esfera en OpenGL ES

Pero no hay nada en ES.

¿Sugerencias/enlaces Tutorial?

+0

echa un vistazo a esta pregunta - http://stackoverflow.com/questions/6072308/problem-drawing-a-sphere-in-opengl-es – alegen

+0

Como la URL ya dice: http://www.learnopengles.com/ android-lesson-one-getting-started/ –

Respuesta

41

Como ha etiquetado esto con OpenGL ES 2.0, permítame sugerir un enfoque alternativo para crear esferas uniformes, y eso es dibujarlas como impostores raytraced. En lugar de calcular los muchos vértices que necesitará para replicar una esfera lisa, puede aprovechar el hecho de que una esfera se ve más o menos igual desde cualquier ángulo.

Para ello, se emplea un proceso como el siguiente:

Sphere impostor generation

te enviará cuatro vértices que representan dos triángulos a un vertex shader, que luego se las desplaza para crear una plaza que siempre enfrenta el usuario. Dentro de ese cuadrado, utiliza un sombreador de fragmentos para crear un ráster sobre cada píxel y proporcionar el color que tendría una esfera en ese punto si lo estuviera viendo a través de esta ventana cuadrada.

La ventaja de este enfoque es que la esfera es tan suave como la resolución de su pantalla es compatible, y la esfera escalará fácilmente de pequeña a grande sin necesidad de volver a calcular su geometría. Cambia la carga de procesamiento del procesador de vértices al procesador de fragmentos, pero para una sola esfera no es un gran problema en los dispositivos OpenGL ES 2.0 con los que he trabajado.

Utilizo esta técnica en this iOS application, para la cual el código fuente está disponible en esa página, y habla un poquito más de here. Una versión simplificada del vertex shader que uso es como la siguiente:

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

y el fragment shader simplificada es la siguiente:

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

Las versiones actuales optimizadas de estos shaders son un poco más difícil de seguir, y también uso iluminación de oclusión ambiental, que no está presente con estos. Tampoco se muestra el texturizado de esta esfera, que se puede hacer con una función de mapeo adecuada para traducir entre las coordenadas de la superficie de la esfera y una textura rectangular. Así es como proporciono valores de oclusión ambiental precalculados para las superficies de mis esferas.

+0

También usé billboard http://williamedwardscoder.tumblr.com/post/13270747573/when-playing-with-game-engine-ideas-i-struggled; mi entrada clave es que para obtener los mejores resultados debe dibujar los bordes en un segundo pase.Abandoné la técnica cuando me moví a OpenGLES 2/webGL porque ya no puedes establecer la profundidad por fragmento :( – Will

+0

¿Qué es la "matriz ortográfica" en Tu código? ¿Es una matriz que convierte un cuadrado al usuario siempre en cara? –

+0

@ SzałPał - Está destinado a corregir la forma no cuadrada de la vista de representación. –

0

Las personas que visitan el hilo anterior pueden consultar el enlace a continuación para crear varios tipos de formas, incluida "Esfera" en OpenGLES2.0.

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

La implementación de la clase de formas hace que sea muy fácil de integra con su código.

Crea una instancia del objeto y utiliza la función de renderizado para dibujar el objeto.

Cuestiones relacionadas