2012-05-07 20 views
13

Voglio disegnare una sfera, so come farlo in OpenGL utilizzando chiamate come glBegin() & glEnd().Disegno di una sfera in OpenGL ES

Ma non c'è niente in ES.

Suggerimenti/Link tutorial?

+0

controlla questa domanda - http://stackoverflow.com/questions/6072308/problem-drawing-a-sphere-in-opengl-es – alegen

+0

Come già dice l'URL: http://www.learnopengles.com/ android-lesson-one-getting-started/ –

risposta

41

Dal momento che l'hai codificato con OpenGL ES 2.0, lasciatemi suggerire un approccio alternativo per la creazione di sfere lisce, che è quello di disegnarle come impostori raytracing. Piuttosto che calcolare i molti vertici necessari per replicare una sfera liscia, puoi approfittare del fatto che una sfera sembra praticamente la stessa da qualsiasi angolazione.

Per fare questo, si impiegano un processo simile al seguente:

Sphere impostor generation

si invia quattro vertici che rappresentano due triangoli ad un vertex shader, che poi li sposta per creare una piazza che si affaccia sempre la utente. All'interno di quel quadrato, usi uno shader di frammenti per rasterizzare su ciascun pixel e fornire il colore che una sfera avrebbe a quel punto se lo stavi visualizzando attraverso questa finestra quadrata.

Il vantaggio di questo approccio è che la sfera è liscia come supporta la risoluzione del display e la sfera scalerà facilmente da piccola a grande senza richiedere alcun ricalcolo della geometria. Sposta l'onere per il rendering dal processore dei vertici al processore dei frammenti, ma per una singola sfera non è un grosso problema sui dispositivi OpenGL ES 2.0 con cui ho lavorato.

Io uso questa tecnica in this iOS application, per cui il codice sorgente è disponibile su quella pagina e ne parlo un po 'di più here. Una versione semplificata del vertex shader che uso simile a questa:

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

e il frammento dello shader semplificata è questo:

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

Le attuali versioni ottimizzate di questi shader sono un po 'più difficile da seguire, e io uso anche l'illuminazione di occlusione ambientale, che non è presente con questi. Inoltre, non viene mostrata la trama di questa sfera, che può essere eseguita con una funzione di mappatura appropriata per tradurre tra le coordinate della superficie della sfera e una trama rettangolare. In questo modo fornisco i valori di occlusione ambientale precalcolati per le superfici delle mie sfere.

+0

Anche io ho usato il cartellone http://williamedwardscoder.tumblr.com/post/13270747573/when-playing-with-game-engine-ideas-i-festated; il mio input chiave è che per ottenere i migliori risultati devi disegnare i bordi in un secondo passaggio.Ho abbandonato la tecnica quando mi spostavo su OpenGLES 2/webGL perché non puoi più impostare la profondità per frammento :( – Will

+0

Qual è il 'orthographicMatrix' nel tuo codice? È una matrice che trasforma un quadrato in un quadrante sempre rivolto all'utente? –

+0

@ SzałPał - È inteso per correggere la forma non quadrata della vista di rendering: –

0

Le persone che visitano il thread precedente possono dare un'occhiata al link fornito qui sotto per creare vari tipi di forme tra cui "Sphere" in OpenGLES2.0.

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

l'implementazione della classe di forme lo rende molto facile si integra con il vostro codice.

Istanziare l'oggetto e utilizzare la funzione di rendering per disegnare l'oggetto.