2012-05-23 10 views
5

Tengo una aplicación de Android que usa OpenGL ES 2.0. Necesito dibujar 10 líneas de una matriz, cada una de las cuales se describe mediante un punto de inicio y un punto final. Entonces hay 10 líneas = 20 puntos = 60 valores de flota. Ninguno de los puntos está conectado, por lo que cada par de puntos en la matriz no está relacionado con los demás, de ahí que dibujo con GL_LINES.Cómo uso un sombreador para colorear líneas dibujadas con GL_LINES y OpenGL ES 2.0

los dibujo, poniendo los valores en un búfer flotador y llamar a algún código ayudante de la siguiente manera:

public void drawLines(FloatBuffer vertexBuffer, float lineWidth, 
     int numPoints, float colour[]) { 
    GLES20.glLineWidth(lineWidth); 
    drawShape(vertexBuffer, GLES20.GL_LINES, numPoints, colour); 
} 

protected void drawShape(FloatBuffer vertexBuffer, int drawType, 
     int numPoints, float colour[]) { 
    // ... set shader ... 
    GLES20.glDrawArrays(drawType, 0, numPoints); 
} 

Los drawLines toma el buffer de flotador (60 carrozas), una anchura de línea, el número de puntos (20) y una matriz de valores de color de 4 flotantes. No he mostrado el código de configuración del sombreador, pero básicamente expone la variable de color al valor uniforme de uColour.

El sombreador de fragmentos que toma uColour simplemente lo conecta directamente a la salida.

/* Fragment */ 
precision mediump float; 

uniform vec4 uColour; 
uniform float uTime; 

void main() { 
    gl_FragColor = uColour; 
} 

El vertex shader:

uniform mat4 uMVPMatrix; 

attribute vec4 vPosition; 

void main() { 
    gl_Position = uMVPMatrix * vPosition; 
} 

Pero ahora quiero hacer algo diferente. Quiero que cada línea en mi buffer tenga un color diferente. Los colores son una función de la posición de la línea en la matriz. Quiero sombrear la línea de inicio en blanco, el último gris oscuro y las líneas entre una gradación entre las dos, p. Ej. #ffffff, #eeeeee, #dddddd etc.

Pude obviamente dibujar cada línea individualmente, conectando un nuevo valor en uColour cada vez, pero eso es ineficiente. No quiero llamar a GL 10 veces cuando podría llamarlo una vez y modificar el valor en un sombreador cada vez.

Quizás podría declarar un valor uniforme llamado uVertexCount en mi vertex shader? Antes del sorteo establezco uVertexCount en 0 y cada vez que se llama al sombreador de vértices, incremente este valor. El sombreador de fragmentos podría determinar el índice de línea mirando uVertexCount. Podría entonces interpolar un valor para el color entre algún valor inicial y final u otro medio. Pero esto depende si cada línea o punto se considera una primitiva o toda la serie de líneas es una sola primitiva.

¿Esto es factible? No sé cuántas veces se llama al sombreador de vértices por fragmento de sombreador. Son las llamadas intercaladas de una manera como esta para hacerlo viable, es decir, vértice 0, vértice 1, fragmento x *, vértice 2, vértice 3, fragmento x * etc.

¿Alguien sabe de algún código de muestra razonable que podría demostrar el concepto o señalarme de alguna otra manera de hacer algo similar?

+0

Por qué no utilizar el color como un atributo? Agregue la información del color en su VertexBuffer. – pearcoding

+0

Podría agregarlo como atributo, pero aún necesito saber el índice de punto/línea en el sombreador de fragmentos para saber qué color del atributo debería usar. es decir, si pasé una matriz de 10 colores como atributo, ¿cómo sabe mi sombreador de fragmentos cuál de los 10 debería estar usando? – locka

+0

no se hace automáticamente ...necesitas el índice si tienes una matriz uniforme, pero no cuando tienes un atributo. Un atributo está conectado a un solo vértice. Entonces, cada uno de tus vértices tiene una posición y un color. – pearcoding

Respuesta

6

Agregue información de color a su Vertexbuffer (Floatbuffer) y use el atributo en su sombreador.

Ejemplo vertexbuffer:

uniform mat4 uMVPMatrix; 

attribute vec4 vPosition; 
attribute vec3 vColor; 

varying vec3 color; 

void main() { 
    gl_Position = uMVPMatrix * vPosition; 
    color = vColor; 
} 

Ejemplo fragmentshader:

precision mediump float; 

varying vec3 color; 

void main() { 
    gl_FragColor = color; 
} 
+0

¿Está sugiriendo que use glDrawElements en lugar de glDrawArray aquí de alguna manera para insertar vColor en el vector sombreador? ¿Se interpola el color o algo de esto o tendré que suministrar el mismo color al punto de inicio/finalización para garantizar que el valor variable no cambie? Trataré de probar esto esta noche para ver cómo me llevo. – locka

+2

Creo que lo tengo ahora. Tengo que vincular glVertexAttribPointer/glEnableVertexAttribArray a una matriz de flotadores para los colores. Probablemente tenga que doblar los colores para cada extremo de la línea, pero eso debería ser lo suficientemente simple. Publicaré una actualización cuando llegue a algún lado con esto. – locka

+0

+1 Sí, este es el camino correcto: D – pearcoding

Cuestiones relacionadas