当前位置: 首页> 娱乐> 明星 > 深圳物流公司大全排名_杭州建设网通知公告栏_百度热搜关键词排名优化_山东泰安网络推广

深圳物流公司大全排名_杭州建设网通知公告栏_百度热搜关键词排名优化_山东泰安网络推广

时间:2025/7/19 6:19:35来源:https://blog.csdn.net/weixin_43833152/article/details/142664505 浏览次数:0次
深圳物流公司大全排名_杭州建设网通知公告栏_百度热搜关键词排名优化_山东泰安网络推广

OpenGL ES 着色器(5)

简述

着色器是在GPU上运行的程序,它会对每一个点都执行一次程序,并且计算出每个像素需要渲染的颜色,我们主要关注着色器的怎么传递数据,在OpenGL ES中,着色器传递数据分几种场景,一种是Cpu传递数据给GPU,一种是顶点缓冲区的数据传递到着色器,还有一种是顶点着色器数据传递给片段着色器。
着色器主要有三种类型传递数据参数:

  • attribute,用于顶点缓冲区数据传递到着色器中。
  • uniform,统一变量,由CPU将数据传递到GPU。
  • varying,用于顶点着色器数据向片段着色器传递。

着色器使用

我们以实现一个颜色渐变的圆形来介绍着色器的使用。
我们之前说过OpenGL渲染都是以三角形为基础的,那应该怎么渲染圆形呢,我的第一反应就是高数里微积分,通过无数个三角形拼接起来,不过这个方案有个问题,我们需要使用多少个三角形才合适,才能让圆形足够圆滑。
虽然GPU更善于执行计算,但是其实GPU也是可以处理逻辑的,所以其实只需要在着色器里做一个简单的逻辑就可以了。
所以我们的思路就是绘制一个正方形,在片段着色器里判断坐标,如果坐标在圆形范围内则为白色, 否则就配置透明的颜色,这样就可以渲染出一个圆形了。

在开始之前,我们需要了解用到的顶点着色器和片段着色器。

顶点着色器

顶点着色器主要用于获取顶点数据,一般是从顶点缓冲区中获取,里面有内置变量gl_Position作为顶点位置的输出,顶点着色器在读取顶点数据并且做预处理后,可以将坐标信息给gl_Position作为输出。
顶点着色器会对每一个顶点都执行一次。

片段着色器

片段着色器用于计算输出的颜色,有一个内置变量gl_FragColor,作为颜色的输出,片段着色器会对每一个像素都执行一次,然后返回该像素需要显示的颜色。
片段着色器可以获取从顶点着色器中获取数据,这里传递数据有两种模式,区别为是否插值,默认是平滑的,会插值的。(就是说几个顶点中的数据会根据坐标线性平滑的渐变,我们之前在顶点缓冲区章节的渐变色三角形demo就是这个原理)

我们想要实现圆形的判断逻辑,需要在片段着色器中处理逻辑,因为片段着色器会对每个像素执行一次。

顶点数据

我们顶点数据为四个顶点,每个顶点7个数据,前三个是坐标,后四个是颜色。
使用索引缓冲区,这里和之前绘制正方形的demo差不多,这里坐标覆盖了全屏幕,作用相当于画板,获取我们会通过一个统一变量来控制圆形半径。

private float[] vertexArray = new float[] {-1.0f, -1.0f, 0.0f, 1f, 1f, 1f, 1f,1.0f, -1.0f, 0.0f, 1f, 1f, 1f, 1f,-1.0f, 1.0f, 0.0f, 1f, 1f, 1f, 1f,1.0f, 1.0f, 0.0f, 1f, 1f, 1f, 1f
};private short[] indexArray = new short[] {0,1,2,1,2,3
};

着色器代码

顶点着色器逻辑:
两个属性,vPosition是坐标,除了直接传给gl_Position外,还通过一个varying的变量传给片段着色器vertexPosition,我们说过这个参数传递默认是会插值的,所以片段着色器拿到的值相当于每个点的坐标。
属性inputColor是从顶点缓冲区中拿的数据,用作颜色,这里通过一个varying变量outputColor传给片段着色器。

private final String vertexShaderCode ="attribute vec4 vPosition;" +"attribute vec4 inputColor;" +"varying vec4 outputColor;" +"varying vec4 vertexPosition;" +"void main() {" +"  gl_Position = vPosition;" +"  vertexPosition = vPosition;" +"  outputColor = inputColor;" +"}";

片段着色器逻辑:
这里有两个传过来的参数,一个为vertexPosition,为像素点坐标位置,一个为outputColor,作为输出颜色。
还有一个统一变量radius作为圆形半径,我们以(0,0)为圆形,这里一个简单几何逻辑,x * x + y * y < radius * radius的部分就是圆形部分,属于圆形部分颜色输出outputColor,否则输出一个透明色。

private final String fragmentShaderCode ="precision mediump float;" +"varying vec4 vertexPosition;" +"varying vec4 outputColor;" +"uniform float radius;" +"void main() {" +"  if (vertexPosition.x * vertexPosition.x + vertexPosition.y * vertexPosition.y > radius * radius) {" +"    gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);" +"  } else {" +"    gl_FragColor = outputColor;" +"  }" +"}";

顶点缓冲区数据填充

这里的逻辑和之前正方形绘制基本一样,就不细说了。

public void onSurfaceCreated(GL10 gl, EGLConfig config) {// 清除颜色GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);// 创建顶点缓冲区int[] idBuffer = new int[2];GLES30.glGenBuffers(2, idBuffer, 0);vertexBufferId = idBuffer[0];elementBufferId = idBuffer[1];// 顶点缓冲区数据填充FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertexArray.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();vertexBuffer.put(vertexArray);vertexBuffer.position(0);GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vertexBufferId);GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertexArray.length * 4,vertexBuffer,GLES30.GL_STATIC_DRAW);GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);ShortBuffer indexBuffer = ByteBuffer.allocateDirect(indexArray.length * 4).order(ByteOrder.nativeOrder()).asShortBuffer();indexBuffer.put(indexArray);indexBuffer.position(0);GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, elementBufferId);GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,indexArray.length * 4,indexBuffer,GLES30.GL_STATIC_DRAW);GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0);// shadershaderProgramId = initShaderProgram(vertexShaderCode, fragmentShaderCode);
}

顶点布局以及渲染

配置顶点缓冲区布局,前三个数作为坐标,后4个数作为颜色。
设置统一变量radius,作为圆形半径。

public void onDrawFrame(GL10 gl) {// 清除屏幕GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);// 使能着色器程序GLES30.glUseProgram(shaderProgramId);// 顶点缓冲区每个顶点前3个数作为坐标GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vertexBufferId);int positionLocation = GLES30.glGetAttribLocation(shaderProgramId, "vPosition");GLES30.glEnableVertexAttribArray(positionLocation);GLES30.glVertexAttribPointer(positionLocation, 3, GLES30.GL_FLOAT, false, 7 * 4, 0);// 顶点缓冲区每个顶点后4个数作为颜色GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vertexBufferId);int inputColorLocation = GLES30.glGetAttribLocation(shaderProgramId, "inputColor");GLES30.glEnableVertexAttribArray(inputColorLocation);GLES30.glVertexAttribPointer(inputColorLocation, 4, GLES30.GL_FLOAT, false, 7 * 4, 3 * 4);// 配置统一变量,圆形半径int radiusLocation = GLES30.glGetUniformLocation(shaderProgramId, "radius");GLES30.glUniform1f(radiusLocation, 0.5f);GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, elementBufferId);// 调用DrawCall绘制三角形GLES30.glDrawElements(GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_SHORT, 0);// 清除配置GLES30.glDisableVertexAttribArray(positionLocation);GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0);GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);GLES30.glUseProgram(0);
}

效果

在这里插入图片描述

小结

看完本节的demo,应该对着色器的使用有了一定的,着色器的语法和C语言有一些类似,不过它其实不是C语言,而是自定义的语言,然后会编辑成显卡驱动可以理解的字节码。
OpenGL ES章节更多的都是以一些简单的demo来介绍,这样会更加容易理解,后面我们会介绍纹理,也会需要在片段着色器中做处理。

关键字:深圳物流公司大全排名_杭州建设网通知公告栏_百度热搜关键词排名优化_山东泰安网络推广

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: