大家好,下面和大學一起學習如何使用片段著色器fragment shader
來渲染豐富多彩的顏色,在我的github上有一個專案OpenGLES2.0SamplesForAndroid
,我會不斷地編寫學習樣例,文章和程式碼同步更新,歡迎關注,連結:github.com/kenneycode/…
在上一篇文章中,我們介紹了渲染管線,下面來回顧一下fragment shader
在渲染管線中的位置:
fragment shader
會在光柵化後,對每個畫素執行一次,先看一下我們之前的例子中使用的fragment shader
:
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
型別。
上篇文章提到過,vertex shader
會對每個頂點都執行一次,而fragment shader
會對每個畫素執行一次,那麼fragment shader
中拿到的v_Color
究竟是什麼值?它是經過插值的值,這個如何理解呢?先來看一下我們這個例子中傳遞的值:
// 顏色資料
// 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)
,我們來看下效果:
程式碼在我github的OpenGLES2.0SamplesForAndroid
專案中,本文對應的是SampleFragmentShader
,專案連結:github.com/kenneycode/…
感謝閱讀!