Android OpenGL ES 2.0 手把手教学(4)- 片断着色器 fragment shader

你们好,下面和大学一块儿学习如何使用片断着色器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 shaderfragment 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_Colorvarying类型变量是一种通过插值后获得的变量,咱们能够看到vertex shader中也声明了一样的varying vec4 v_Color,而后将a_Color赋给v_Colorfragment shader中的v_Color就是经过vertex shader传递过来的,而a_Colora_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

相关文章
相关标签/搜索