OpenGL ES shading language 3.0 也被称作 GLSL,是个 C风格的编程语言。

Opengl ES 3.0内部有两种可编程处理单元,即Vertex processor和Fragment processor,分别用来处理Vertex shader executable和Fragment shader executable。注意,Opengl ES 3.0不支持Geometry Shader。上图中,紫色部分就是可执行体了,即 executable .

先来一段Vertex shader代码

#version  es //版本号
in vec4 VertexPosition; //应用层输入逐顶点位置坐标数据
in vec4 VertexColor; //应用层输入逐顶点颜色数据
uniform float RadianAngle; //应用层输入数据
out vec4 TriangleColor;
mat2 rotation = mat2(cos(RadianAngle),sin(RadianAngle),
-sin(RadianAngle),cos(RadianAngle));
void main()
{
  gl_Position = mat4(rotation)*VertexPosition;//给内置数据赋值   TriangleColor = VertexColor;
}

再来一段Fragment shader代码

#version  es
precision mediump float;//配置精度
in vec4 TriangleColor;
out vec4 FragColor;
void main() {
FragColor = TriangleColor;
};

上面这两段代码,只是文本数据,上述的两种processor可没办法直接执行,这就需要一个叫做编译和链接的步骤,来将这个文本数据变成executable的数据。可以通过下图来了解这个创建executable的过程:

需要在应用层加载和编译shader,使用如下代码进一步说明:

GLuint loadAndCompileShader(GLenum shaderType, const char* sourceCode) 
{
  // Create the shader
  GLuint shader = glCreateShader(shaderType);
  if ( shader )
  {
    // Pass the shader source code
    glShaderSource(shader, , &sourceCode, NULL);
    // Compile the shader source code
    glCompileShader(shader);
    // Check the status of compilation
    GLint compiled = ;
    glGetShaderiv(shader,GL_COMPILE_STATUS,&compiled);
    if (!compiled)
    {
    // Get the info log for compilation failure
    GLint infoLen = ;
    glGetShaderiv(shader,GL_INFO_LOG_LENGTH, &infoLen);
    if (infoLen)
    {
      char* buf = (char*) malloc(infoLen);
      if (buf)
      {
        glGetShaderInfoLog(shader, infoLen, NULL, buf);
        printf("Could not compile shader %s:" buf);
        free(buf);
      }
    // Delete the shader program
    glDeleteShader(shader);
    shader = ;
    }
  }
}
return shader;
}

使用如下代码来执行链接过程:

GLuint linkShader(GLuint vertShaderID,GLuint fragShaderID){
if (!vertShaderID || !fragShaderID){ // Fails! return
return ;
}
// Create an empty program object
GLuint program = glCreateProgram();
if (program) {
// Attach vertex and fragment shader to it
glAttachShader(program, vertShaderID);
glAttachShader(program, fragShaderID);
// Link the program
glLinkProgram(program);
GLint linkStatus = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE) {
GLint bufLength = ;
glGetProgramiv(program, GL_INFO_LOG_LENGTH,
&bufLength);
if (bufLength) {
char* buf = (char*) malloc(bufLength);
if(buf) { glGetProgramInfoLog(program,bufLength,NULL,buf);
printf("Could not link program:\n%s\n", buf);

free(buf);
}
}
glDeleteProgram(program);
program = 0;
}
}
return program;
}

前文一直提到的executable就是这个返回的句柄变量 program。这个program将会在流水线的Processor上执行。

回过头再来分析vertex shader代码和fragment shader代码。

in vec4 VertexPosition;
in vec4 VertexColor;

shader代码里声明的这两个变量的值是从哪里获取的呢,这就涉及了一个重要的环节,就是应用层和shader层的数据通信问题。为了方便理解,根据执行的位置不同,可以把应用层看做CPU,把shader层看做GPU。即可抽象为CPU与GPU通信,进一步抽象为客户端C和服务端S之间的通信。下面来解释这个通信的流程,从通信上来说,必然是要先让客户端找到服务器端的一个通信端口,然后客户端建立与这个通信端口的连接,最后只要往这个连接上扔数据,这样服务端就能收到数据了。

首先实现寻找到服务端通信端口的功能,以下代码就帮助CPU端找到GPU端的数据通信端口

GLuint positionAttribHandle;
GLuint colorAttribHandle; positionAttribHandle = glGetAttribLocation(programID, "VertexPosition");
colorAttribHandle = glGetAttribLocation(programID, "VertexColor");

以下代码,实现了往通信通道上扔数据的功能:

// Send data to shader using queried attrib location
glVertexAttribPointer(positionAttribHandle, , GL_FLOAT,GL_FALSE, , gTriangleVertices);
glVertexAttribPointer(colorAttribHandle, , GL_FLOAT,GL_FALSE, , gTriangleColors);

GPU端,默认所有这些顶点属性端口都是关闭的,因此需要打开这些通信端口:

// Enable vertex position attribute
glEnableVertexAttribArray(positionAttribHandle);
glEnableVertexAttribArray(colorAttribHandle);

这样,一条通信信道就算建立起来了。

梳理 Opengl ES 3.0 (二)剖析一个GLSL程序的更多相关文章

  1. 梳理 Opengl ES 3.0 (一)宏观着眼

    Opengl ES 可以理解为是在嵌入式设备上工作的一层用于处理图形显示的软件,是Opengl 的缩水版本. 下图是它的工作流程示意图: 注意图中手机左边的EGL Layer Opengl ES是跨平 ...

  2. 梳理 Opengl ES 3.0 (三)顶点坐标变换

    先来个宏观上的理解: 其实这块逻辑是个标准流程,而且其他地方介绍的也很多了,这里简单提下. 坐标转换,其实是不同坐标系之间的变换,一个渲染顶点,要想让它呈现在屏幕上的某个位置,是需要让这个顶点经过一个 ...

  3. 梳理 Opengl ES 3.0 (五)shader运行原理

    先来看看一张图 shader都是在运行时编译和执行的,每个shader都有一个main函数作为它的入口. vertex shader的功能有两个:一个是计算顶点坐标变换,另一个就是为片元shader计 ...

  4. OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型

    OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...

  5. OpenGL ES 3.0 基础知识

    首先要了解OpenGL的图形管线有哪些内容,再分别去了解其中的相关的关系: 管线分别包括了顶点缓冲区/数组对象,定点着色器,纹理,片段着色器,变换反馈,图元装配,光栅化,逐片段操作,帧缓冲区.其中顶点 ...

  6. [置顶] 使用Android OpenGL ES 2.0绘图之五:添加运动

    传送门 ☞ 系统架构设计 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 传送门 ☞ GoF23种设计模式 ☞ 转载请注明 ☞ http://blog.csd ...

  7. OpenGL ES 2.0 渲染管线 学习笔记

    图中展示整个OpenGL ES 2.0可编程管线 图中Vertex Shader和Fragment Shader 是可编程管线: Vertex Array/Buffer objects 顶点数据来源, ...

  8. Android OpenGL ES 开发(二): OpenGL ES 环境搭建

    零:环境搭建目的 为了在Android应用程序中使用OpenGL ES绘制图形,必须要为他们创建一个视图容器.其中最直接或者最常用的方式就是实现一个GLSurfaceView和一个GLSurfaceV ...

  9. 【Android 应用开发】OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解

    最近开始关注OpenGL ES 2.0 这是真正意义上的理解的第一个3D程序 , 从零开始学习 . 案例下载地址 : http://download.csdn.net/detail/han120201 ...

随机推荐

  1. HDU 1110 Equipment Box (判断一个大矩形里面能不能放小矩形)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1110 Equipment Box Time Limit: 2000/1000 MS (Java/Oth ...

  2. 【Linux-CentOS】CentOS安装Win双系统后Win启动项丢失及默认启动项修改

    转载自:搁浅bky,有部分更正,建议看此文. 1.Windows启动项消失的原因:   在安装Win7.8/10系统+CentOS7双系统后,默认会将mbr(Main Boot Record)改写为g ...

  3. WPF中 ItemsSource 和DataContext不同点

    此段为原文翻译而来,原文地址 WPF 中 数据绑定 ItemSource和 DataContext的不同点: 1.DataContext 一般是一个非集合性质的对象,而ItemSource 更期望数据 ...

  4. Python学习之路——基础2(含深浅拷贝)

    逻辑运算符:not  and  or 等同于c/c++中的 !.&&.||,除了写法上的不同,实际原理是一样的. 运算也遵循短路原则.由于Python本身不支持++/--操作符,所以避 ...

  5. 兼容性良好的 sticky-footer 布局

    <div class="content"> <div class="content-wrapper"> <div class=&q ...

  6. HIbernate jar包

    密码nbbk https://pan.baidu.com/share/init?surl=nYNO1f20FWMQiZ7iN11DIA

  7. 有连接服务&无连接服务

    面向连接的服务 通信双方在通信时要事先建立一条通信线路,其过程包括建立连接.使用链接.释放链接三个过程 如: TCP 电话 面向无连接的服务 通信双方不需要事先建立一条通信线路,而是把每个带有目的选址 ...

  8. Java秒杀系统方案优化 高性能高并发实战(已完成)

    1:商品列表 2:商品详情判断是否可以开始秒杀,未开始不显示秒杀按钮显示倒计时,开始显示秒杀按钮,同时会显示验证码输入框以及验证码图片,当点击秒杀按钮的时候会首先判断验证码是否正确,如果正确会返回一个 ...

  9. mysql5.7 本地计算机上的mysql 服务启动后停止 的问题解决

    mysql5.7 本地计算机上的mysql 服务启动后停止. 问题: 在cmd 下mysql服务mysql服务无法启动任何错误法启动 服务没有报告任何错误     在服务里面启动是   早上来了发现项 ...

  10. java 代码调用函数

    sql 中调用函数 getDistance(lng1 float, lat1 float, lng2 float, lat2 float) 例如: SELECT id, f_seller_id sel ...