大家好,这是我的OpenGL ES
高级进阶系列文章,在我的github
上有一个与本系列文章对应的项目,欢迎关注,链接:github.com/kenneycode/…
今天给大家介绍OpenGL ES 3.0
的shader
中一些新关键字的特性,我们与OpenGL ES 2.0
的shader
作对比来看看这些新特性。
我们先来看看OpenGL ES 2.0
的两个普通的vertex shader
和fragment shader
:
// vertex shader
precision mediump float;
attribute vec4 a_position;
attribute vec2 a_textureCoordinate;
varying vec2 v_textureCoordinate;
void main() {
v_textureCoordinate = a_textureCoordinate;
gl_Position = a_position;
}
// fragment shader
precision mediump float;
attribute vec4 fragColor;
uniform sampler2D s_texture;
varying vec2 v_textureCoordinate;
void main() {
gl_FragColor = texture2D(s_texture, v_textureCoordinate);
}
在OpenGL ES 2.0
中,我们想往一个shader
参数中传递数据时,先要获取对应的location
,例如,我们给a_position
传递数据:
val location = GLES20.glGetAttribLocation(programId, "a_position")
// 启动对应位置的参数
// Enable the parameter of the location
GLES20.glEnableVertexAttribArray(location)
// 指定a_Position所使用的顶点数据
// Specify the vertex data of a_Position
GLES20.glVertexAttribPointer(location, VERTEX_COMPONENT_COUNT, GLES20.GL_FLOAT, false, 0, buffer)
而在OpenGL ES 3.0
中,我们可以直接在shader
中指定参数的location
,而不需要像在OpenGL ES 2.0
中那样通过API
获取参数的location
,我们来将上面两个shader
改写成OpenGL ES 3.0
的版本:
// vertex shader
#version 300 es
precision mediump float;
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec2 a_textureCoordinate;
out vec2 v_textureCoordinate;
void main() {
v_textureCoordinate = a_textureCoordinate;
gl_Position = a_position;
}
// fragment shader
#version 300 es
precision mediump float;
layout(location = 0) out vec4 fragColor;
layout(location = 0) uniform sampler2D s_texture;
in vec2 v_textureCoordinate;
void main() {
fragColor = texture(s_texture, v_textureCoordinate);
}
首先需要在开头处标明shader
版本#version 300 es
,
我们可以看到,我们给参数加上了layout(location = x)
这样的语句,例如给a_position
加上了layout(location = 0)
,即指定它的location
是0
,于是我们可以直接通过操作0
号location
的参数来操作a_position
:
val LOCATION_ATTRIBUTE_POSITION = 0
// 启动对应位置的参数,这里直接使用LOCATION_ATTRIBUTE_POSITION,而无需像OpenGL 2.0那样需要先获取参数的location
// Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_POSITION, while in OpenGL 2.0 we have to query the location of the parameter
GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
// 指定a_position所使用的顶点数据
// Specify the data of a_position
GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false, 0, vertexDataBuffer)
另外,我们还能看到之前的attribute
、varying
关键写变成了in
和out
,这比较容易理解,在OpenGL ES 2.0
中,attribute
就是输入,varying
就是从vertex shader
往fragment shader
的输出,还可以看到,内置的gl_FragColor
被我们改写成了一个out
变量来代码fragment shader
的输出,为何需要这样呢?gl_FragColor
代表输出不就够了吗?为什么需要自己指定?这是因为在OpenGL ES 3.0
中支持**多渲染目标(MRT)**这个新特性,即可以在fragment shader
中指定多个输出,这个特性我后面也会介绍,欢迎关注。
代码在我github
的OpenGLESPro
项目中,本文对应的是SampleShader
,项目链接:github.com/kenneycode/…
感谢阅读!