2016-01-06 4 views
1

Пытается изменить значения цветов вершин треугольника от Android Developer OpenGL Tutorial. Треугольник отображается, но кажется темным. Что не так с цветовым буфером?Неоднородные значения цвета для фрагментарного шейдера в OpenGL ES 2.0

public class Triangle { 

    ... 

Добавлены следующие строки для создания цветового буфера. Это необходимо?

private FloatBuffer colorBuffer; 
    static final int COLORS_PER_VERTEX = 4; 

    static float triangleColors[] = { 
      0.6f, 0.2f, 0.2f, 1.0f, 
      0.2f, 0.6f, 0.2f, 1.0f, 
      0.9f, 0.9f, 0.2f, 1.0f 
    }; 

    private final int colorStride = COLORS_PER_VERTEX * 4; 

С помощью следующих кодов шейдерных заменить оригинальный «единообразного vec4 vColor» с атрибутом вместо изменения, потому что нет GLES20.getVaryingLocation.

private final String vertexShaderCode = 
     "attribute vec4 vPosition;void main(){gl_Position = vPosition;}"; 

    private final String fragmentShaderCode = 
      "precision mediump float;" + 
        //originally uniform, use varying? 
        "attribute vec4 vColor;" + 
        "void main() {" + 
        " gl_FragColor = vColor;"+ 
        "}"; 

В конструкторе:

public Triangle() 
    { 
     ... 

     ByteBuffer cb = ByteBuffer.allocateDirect(triangleColors.length * 4); 
     cb.order(ByteOrder.nativeOrder()); 
     colorBuffer = cb.asFloatBuffer(); 
     colorBuffer.put(triangleColors); 
     colorBuffer.position(0); 

     ... //compile and link shaders code is unchanged 
    } 

    public void draw() 
    { 
     GLES20.glUseProgram(mProgram); 

     ... 

     /* 
     mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); 
     GLES20.glUniform4fv(mColorHandle, 1, color, 0); 
     */ 

     mColorHandle = GLES20.glGetAttribLocation(mProgram, "vColor"); 
     GLES20.glEnableVertexAttribArray(mColorHandle); 
     GLES20.glVertexAttribPointer(mColorHandle, COLORS_PER_VERTEX, 
       GLES20.GL_FLOAT, false, colorStride, colorBuffer); 

     GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); 
     GLES20.glDisableVertexAttribArray(mPositionHandle); 
     GLES20.glDisableVertexAttribArray(mColorHandle); 

    } 

} 

ответ

1

Вы недопонимание, что является однородным, атрибут и изменяющееся.

Чтобы сделать изменение, которое вы описываете, вам нужны как атрибут, так и переменный. Вершинный шейдер должен включать атрибут для цвета, такого как attribute vec4 aColor;, и изменяющийся выход как varying vec4 vColor;. Затем в основном вам необходимо назначить цвет как vColor = aColor;. В шейдере фрагмента вам нужно только varying vec4 vColor; и использовать его так же, как в основном методе.

Чтобы объяснить немного о каких именно:

  • атрибут и равномерная очень похожи, но атрибут для каждой вершины в то время как униформа за вызов отрисовки (будет иметь такое же значение для всех вершин, фрагментов). Они оба предназначены для обеспечения связи между процессором и графическим процессором (вы отправляете данные на GPU через любой из них).
  • Разнообразно отличается. Обычно переменная назначается из атрибута и выполняется в вершинном шейдере. Это означает, что каждая вершина будет иметь свое значение из атрибута, но после того, как растеризация будет выполнена, каждое из изменяющегося значения будет интерполировано в зависимости от положения фрагмента относительно ограничивающих вершин. Поэтому переменная предназначена для связи между вершиной и шейдером фрагмента (отправка данных с вершины на фрагментарный шейдер).

Проще всего объяснить на линии, определенной двумя точками (A,B), и, скажем, на вашем буфере визуализации линия займет 100 пикселей. Если первая строка имеет белый цвет C1 = (1,1,1,1), а вторая точка имеет черный цвет C2 = (0,0,0,1). Вы будете назначать один и тот же цвет в вершинном шейдере для изменяющегося значения, а фрагментарный шейдер будет называться 100 раз, что для каждого из пикселей. Теперь ваш различный цвет в шейдере фрагмента будет иметь интерполированное значение для позиции X, как в

color = C1 + (C2-C1)*((X-A).length()/(B-A).length()).

Таким образом, для случая 100 пикселей 46-й пиксель будет

color = (1,1,1,1)-(1,1,1,0)*(64/100)

что приводит к (.36, .36, .36, 1.0). Таким образом, пиксели будут линейно исчезать до черного от A до B, что приведет к хорошему градиенту.

Надеюсь, это немного прояснит ситуацию.

+0

Отлично, это очищает. Спасибо за тщательный ответ! –

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