你们好,下面和大学一块儿学习如何使用片断着色器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