您的位置:首页 > 其它

着色器的编译和屏幕上面绘图

2016-09-27 00:00 134 查看
关于opengl es的着色器语言,我推荐一个地址:http://imgtec.eetrend.com/blog/1948,这篇文章写的相当不错,大家要是有兴趣可以去看一下。

我在这里简单总结一下,uniform在着色器中是只读的,不能被修改,它的值只能被opengl es的API注入。Attribute相当于opengl es的API向顶点着色器注入数据的入口,它与uniform的不同之处在于:uniform是全局常量,该全局性对顶点着色器与片元着色器均可见;Attributes是针对每一个顶点的输入数据,而且只能在顶点着色器中使用。varying用于从顶点着色器向片段着色器传递数据,在光栅化阶段,varying变量会被做线性插值处理。

我们接着讲对着色器的编译。

在Android里面,着色器文件一遍都放在raw文件夹下面,因此我们要先把内容读取到内存中,接下来的步骤如下:

1.创建新的着色器对象。

int shaderID = GLES20.glCreateShader(type);

这里的type可以代表顶点着色器的 GLES20.GL_VERTEX_SHADER,和片段着色器的GLES20.GL_FRAGMENT_SHADER。

2.上传和编译着色器的源代码

GLES20.GLES20.glShaderSource(shaderID, shaderCode);
GLES20.glCompileShader(shaderID);

这里的shaderCode表示从raw文件夹下读取的顶点着色器或片段着色器的字符串内容。

3.对顶点着色器和片段着色器执行第一步和第二步的操作。

4.新建一个opengl程序,注意,这里的程序指的是opengl中的组件。

int programID = GLES20.glCreateProgram();

5.将我们之前创建的顶点着色器和片段着色器的ID附加到这个opengl的程序上。

GLES20.glAttachShader(programID, vertexShaderID);
GLES20.glAttachShader(programID, fragmentShaderID);

6.链接程序,把顶点着色器和片段着色器链接起来。

GLES20.glLinkProgram(programID);

7.使用我们创建的opengl程序

GLES20.glUseProgram(programID);

然后我们讲讲如何将数据通过opengl es接口注入到着色器当中去。我们以下边的着色器为例:

顶点着色器

attribute vec4 a_Position;

void main()
{
gl_Position = a_Position;
}

片段着色器:

precision mediump float;

uniform vec4 u_Color;

void main()
{
gl_FragColor = u_Color;
}

给uniform属性注入数据:

1. GLES20.获得uniform的位置

String U_COLOR = "u_Color";

int colorPosition = GLES20.glGetUniformLocation(program, U_COLOR);

2.把数据传递给uniform

GLES20.glUniform4f(colorPosition, 1, 1, 1, 1);

给Attribute属性注入数据:

1.获得属性的位置

String A_POSITION = "a_Position";

positionLocation = GLES20.glGetAttribLocation(program, A_POSITION);

2.关联属性与顶点数据的数组

GLES20.glVertexAttribPointer(positionLocation, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT, false, 0, vertexArray);

3.启动该顶点数组

GLES20.glEnableVertexAttribArray(positionLocation);

此外还有关于绘制部分,绘制可以分为三种绘制方式:数组绘制,顶点索引绘制,缓冲区绘制

1.数组绘制,GLES20.glDrawArrays(type, startPosition, count);

2.顶点 索引绘制,GLES20.glDrawElements(type, indexCount, dataType, indexArray);

3.缓冲区绘制分为缓冲区对象的创建和缓冲区的绘制。缓冲区分为顶点缓冲区和索引缓冲区。

比如顶点缓冲区对象的创建:

int buffers[] = new int[1];

GLES20.glGenBuffers(length,)//生成缓冲区

bufferID = buffers[0];

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);//绑定缓冲区

FloatBuffer vertexArray = ................//生成floatBuffer,并且注入数据

vertexArray.position(0);

GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexArray.capacity()*BYTES_PER_FLOAT, vertexArray, GLES20.GL_STATIC_DRAW); //将native中的数据传入到GPU

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);//解除绑定

创建索引缓冲区对象和创建顶点缓冲区对象其实差不多,只需要对上面的代码做如下改动:

1.使用short[]和ShortBuffer作为类型

2.使用GLES20.GL_ELEMENT_ARRAY_BUFFER,而不是GLES20.GL_ARRAY_BUFFER

通过缓冲区绘制,可以使用GLES20.glDrawElements(),只是使用前和使用后需要绑定和解除缓冲区的绑定。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: