2791146769ad632523823cfaf761badc
基础部分(二):OpenGL中的着色器知识

目录

  • 前言
    • 推荐
    • 前言
    • 目标
  • 目前主流图形框架
  • OpenGL 着色器(GLSL)
    • 顶点着色器
    • 片段着色器

推荐:

这个网站是我一开始接触OpenGL 时的最佳学习网站,而且是中文,有作者的理解。

前言

本文写了很久,一直处于删减状态;担心写的详细变成了长篇大论,又担心写少了,难以理解。于是本着认知转化的原则,写出了这篇文章,如果有理解不到位的,欢迎指正。

建议:

学习OpenGL、Metal最难的就是理解,理解这种思维模式,就像我们在工作中使用组件化,MVVM或者是某种思想;OpenGL、Metal是一种图形编码接口,请注意OpenGL、Metal 不是一门语言。

近期又读了本文一次,发现信息量较大,不易理解,于是拆分成两篇文章(OpenGL 和Metal 着色器)。

目标:

本文,你只需关注着色器,不要关心其他实现,理解着色器(vertex、fragment)的工作原理就好。

此外,学完本文之后,大家可以模仿写几个着色器:放到我下文提到的Demo中。

建议实现以下着色器:

  • 只显示图片的一部分,比如:圆形区域、左边显示图片,右边显示黑色
  • 动态改变,显示的圆形区域的半径(参考SplitFilter)
目前主流图形框架
  • Metal
  • Vukan
  • OpenGL
  • DX12

OpenGL 着色器(GLSL)

名词:顶点着色器 Vertex Shader 、片段着色器 Fragment Shader

渲染流程

在开始本文之前,请确认:自己曾经了解过着色器,了解过渲染流程。
否则请常查看https://learnopengl-cn.github.io 第四章 可能需要VPN

看完这篇文章需要了解:

  • 顶点着色器:图形渲染管线的第一个部分
  • 片段着色器:主要目的是计算一个像素的最终颜色
  • 着色器也是一种非常独立的程序,因为它们之间不能相互通信;它们之间唯一的沟通只有通过输入和输出
  • 在OpenGL ES中 表示输入输出的关键字为 inout
  • Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同。uniform是全局的(Global)、通常用作变量,下文会介绍。
  • 在整个渲染流程中我们只编程 顶点着色器 以及 片段着色器就可以了,能满足我们的绝大部分需求。

我用通俗的话解释一下这个流程,假如我们渲染一张图片到屏幕上,假如,就是下边的这个图片

需要渲染的图片

需要渲染的图片

我们该怎么做?

首先,我们先简单点,不考虑纹理,只考虑显示一个矩形,内部颜色就暂定为红色:
红色

红色

  • 我们知道红色对应的rgb 是 -> (255,0,0) ,这种对应关系是规定。
  • 矩形需要四个点,按照一定顺序用直线连接起来(虽然是三角形拼接的,但是先这样理解)。顶点着色器 接受这些点的数据
  • 片段着色器 就是决定最后输出的颜色的,我们既然选择固定颜色红色,那么就不需要Uniform。
  • 如果这个颜色是根据时间动态变化的,那么Uniform 就是那个变值,具体的变化情况,由映射关系确定。

为了方便我这边copy 来自 [https://learnopengl-cn.github.io 第四章] 着色器。

顶点着色器
#version 330 core
layout (location = 0) in vec3 position; // position变量的属性位置值为0

out vec4 vertexColor; // 为片段着色器指定一个颜色输出

void main()
{
    gl_Position = vec4(position, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数
    vertexColor = vec4(1.0f, 0.0f, 0.0f, 1.0f); // 把输出变量设置为红色
}

glsl中的向量(vec2,vec3,vec4)往往有特殊的含义,比如可能代表了一个空间坐标(x,y,z,w),或者代表了一个颜色(r,g,b,a),再或者代表一个纹理坐标(s,t,p,q) 所以glsl提供了一些更人性化的分量访问方式.

  • vector.xyzw 其中xyzw 可以任意组合

  • vector.rgba 其中rgba 可以任意组合

  • vector.stpq 其中stpq 可以任意组合

类型 说明
void 空类型,即不返回任何值
top Created with Sketch.