你們好,下面和大學一塊兒學習如何使用片斷着色器fragment shader
來渲染豐富多彩的顏色,在個人github上有一個項目OpenGLES2.0SamplesForAndroid
,我會不斷地編寫學習樣例,文章和代碼同步更新,歡迎關注,連接:github.com/kenneycode/…java
在上一篇文章中,咱們介紹了渲染管線,下面來回顧一下fragment shader
在渲染管線中的位置:git
fragment shader
會在光柵化後,對每一個像素執行一次,先看一下咱們以前的例子中使用的fragment shader
:github
precision mediump float;
void main() {
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
複製代碼
在一開始聲明瞭float
的精度爲中精度,接着和vertex shader
同樣有一個main()
方法做爲入口,fragment shader
中有一個內置變量gl_FragColor
表示fragment shader
的輸出,在以前的例子咱們給gl_FragColor
設置了一個固定值vec4(0.0, 0.0, 1.0, 1.0)
,這是一個RGBA
的顏色值,所以咱們以前看到的三角形是一個純藍色的,如今,咱們來實現一個彩色的三角形,這須要vertex shader
和fragment shader
同時修改,來看看咱們修改後的shader
:學習
// vertex shader
precision mediump float;
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
v_Color = a_Color;
gl_Position = a_Position;
}
複製代碼
// fragment shader
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
複製代碼
修改後,gl_FragColor
再也不是一個固定值,而是一個類型爲varying
的顏色值v_Color
,varying
類型變量是一種通過插值後獲得的變量,咱們能夠看到vertex shader
中也聲明瞭一樣的varying vec4 v_Color
,而後將a_Color
賦給v_Color
,fragment shader
中的v_Color
就是經過vertex shader
傳遞過來的,而a_Color
和a_Position
同樣是attribute
類型。ui
上篇文章提到過,vertex shader
會對每一個頂點都執行一次,而fragment shader
會對每一個像素執行一次,那麼fragment shader
中拿到的v_Color
到底是什麼值?它是通過插值的值,這個如何理解呢?先來看一下咱們這個例子中傳遞的值:spa
// 顏色數據
// The color data
private val colorData = floatArrayOf(
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f)
// 每一個顏色的成份數(RGBA)
// The num of components of per color(RGBA)
private val COLOR_COMPONENT_COUNT = 4
// 將三角形頂點數據放入buffer中
// Put the triangle vertex data into the buffer
val colorDataBuffer = ByteBuffer.allocateDirect(colorData.size * java.lang.Float.SIZE)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
colorDataBuffer.put(colorData)
colorDataBuffer.position(0)
// 獲取字段a_Color在shader中的位置
// Get the location of a_Color in the shader
val aColorLocation = GLES20.glGetAttribLocation(programId, "a_Color")
// 啓動對應位置的參數
// Enable the parameter of the location
GLES20.glEnableVertexAttribArray(aColorLocation)
// 指定a_Color所使用的頂點數據
// Specify the vertex data of a_Color
GLES20.glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GLES20.GL_FLOAT, false,0, colorDataBuffer)
複製代碼
咱們以與傳遞三角形頂點給a_Position
相同的方式,將三個顏色值(1.0f, 0.0f, 0.0f, 1.0f)
、(0.0f, 1.0f, 0.0f, 1.0f)
和(0.0f, 0.0f, 1.0f, 1.0f)
傳遞給a_Color
,這時在vertex shader
執行時會同時取到頂點和顏色數據的同一位置的數據,將這三個顏色值傳遞給v_Color
後,在fragment shader
中的v_Color
就是通過這三個顏色值插值後的值,例如越靠近顏色(1.0f, 0.0f, 0.0f, 1.0f)
對應的點的地方,顏色就越接近(1.0f, 0.0f, 0.0f, 1.0f)
,咱們來看下效果:code
代碼在我github的OpenGLES2.0SamplesForAndroid
項目中,本文對應的是SampleFragmentShader
,項目連接:github.com/kenneycode/…component
感謝閱讀!cdn