2021SC@SDUSC Ebiten(三) 着色器代码详解

2021SC@SDUSC

Go语言的简单2D游戏库-Ebiten   

 

目录

1、什么是着色器?

2、Ebiten API

NewShader

(*Image).DrawRectShader

DrawRectShaderOptions

其他

3、阴影语言Kage

句法

入口点

内置类型

内置类型的初始化函数

Swizzling

统一变量

内置函数 (Go)

内置函数(数学)

内置函数(图像)

纹理和图像


1、什么是着色器?

着色器是在 GPU 上执行的程序。自定义着色器是 Ebiten 用户可以编写的着色器。使用着色器,可以高效地在 GPU 上执行复杂的渲染。

在 Ebiten 中,可以编写“片段着色器”。片段着色器是在每个像素上执行的着色器。粗略地说,这是一个为每个像素计算颜色的函数。此颜色计算在 GPU 上并行执行。

使用着色器,可以执行各种效果,例如照明或模糊。

go run -tags=example github.com/hajimehoshi/ebiten/v2/examples/shader@latest

Ebiten 采用了原始的着色语言“Kage”。这与 Go 具有兼容的语法,但细节不同。Kage具有很高的便携性。Ebiten 使用 OpenGL 或 Metal 等图形库,这取决于环境,但 Kage 是即时编译的,因此它在任何地方都可以正常工作。

例子

package main

// Uniform variables.
var Time float
var Cursor vec2
var ScreenSize vec2

// Fragment is the entry point of the fragment shader.
// Fragment returns the color value for the current position.
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
	// You can define variables with a short variable declaration like Go.
	lightpos := vec3(Cursor, 50)
	lightdir := normalize(lightpos - position.xyz)
	normal := normalize(imageSrc1UnsafeAt(texCoord) - 0.5)
	ambient := 0.25
	diffuse := 0.75 * max(0.0, dot(normal.xyz, lightdir))

	// You can treat multiple source images by
	// imageSrc[N]At or imageSrc[N]UnsafeAt.
	return imageSrc0UnsafeAt(texCoord) * (ambient + diffuse)
}

2、Ebiten API

NewShader

func NewShader(src []byte) (*Shader, error)

NewShader 用着色语言 Kage 编译着色器程序,并返回结果。

如果编译失败,则NewShader返回错误。

(*Image).DrawRectShader

func DrawRectShader(width, height int, shader *Shader, options *DrawRectShaderOptions)

DrawRectShader 使用指定的着色器绘制具有指定宽度和高度的矩形。

DrawRectShaderOptions

type DrawRectShaderOptions struct {
    // GeoM is a geometry matrix to draw.
    // The default (zero) value is identity, which draws the rectangle at (0, 0).
    GeoM GeoM

    // CompositeMode is a composite mode to draw.
    // The default (zero) value is regular alpha blending.
    CompositeMode CompositeMode

    // Uniforms is a set of uniform variables for the shader.
    // The keys are the names of the uniform variables.
    // The values must be float or []float.
    // If the uniform variable type is an array, a vector or a matrix,
    // you have to specify linearly flattened values as a slice.
    // For example, if the uniform variable type is [4]vec4, the number of the slice values will be 16.
    Uniforms map[string]interface{}

    // Images is a set of the source images.
    // All the image must be the same size with the rectangle.
    Images [4]*Image
}

其他

对于更原始的渲染,还有(*Image).DrawTrianglesShaderDrawTrianglesShaderOptions

3、阴影语言Kage

句法

语法与 Go 基本相同。这在语法级别上完全相同。你甚至可以做到gofmt

到目前为止,Kage 还没有这些 Go 的功能。

  • 大多数类型(runestring, 除intinterface、切片、指针、结构、函数类型、通道外的数字类型)
  • 内置函数len(例如,newmakepanic
  • 新的类型定义 type
  • 结构
  • import
  • switch
  • goto
  • for-range
  • 协程
  • defer
  • init 职能
  • 方法定义

入口点

Kage 只能定义一个片段着色器。Fragment具有以下输入参数的函数是入口点。

func Fragment(position vec4, texCoord vec2, color vec4) vec4
姓名 类型 描述
position vec4 以像素为单位的目标位置。第 3 和第 4 分量始终为 0 和 1。
texCoord vec2 源纹理在纹素中的位置。
color vec4 从顶点给出的补充颜色信息。每个组件的值都在 0 到 1 之间。这个值只有在DrawTrianglesShader使用时才有意义。
(返回值) vec4 当前位置的颜色。每个组件的值都在 0 到 1 之间。

内置类型

Kage 有这些内置类型。

  • bool
  • int
  • float
  • vec2vec3vec4(矢量)
  • mat2mat3mat4(矩阵)

float是一个浮点数。与 Go 的float32and不同float64float它不能保证精度。

vec2vec3,vec4称为向量,是分别具有 2、3 和 4 个分量的元组。每个组件都是float. Swizzling 操作可用于向量值。

mat2mat3,mat4是 2、3 和 4 维方阵。每个组件都是float.

Kage 还支持数组。Kage 不支持结构体。

内置类型的初始化函数

与 Go 类似,您可以通过将类型名称用作函数来获取类型的值。向量类型和矩阵类型非常特殊,它们可以采用灵活的参数。

v1 := vec4(0)              // Returns a vec4 whose components are all 0.
v2 := vec4(1, 2, 3, 4)     // Returns a vec4 whose components are 1, 2, 3 and 4.
v3 := vec3(5, 6, 7)
v4 := vec4(1, v3)          // Returns a vec4 whose components are 1, 5, 6 and 7.

m1 := mat4(2)              // Returns a mat4 whose diagonal components are 2 and the others are 0.
m2 := mat4(v1, v2, v3, v1) // Returns a mat4 whose columns are v1, v2, v3 and v1.

Swizzling

有一个特殊的操作叫做 Swizzling -搅拌 用于向量类型。可以同时读写多个组件。

v1 := vec4(1, 2, 3, 4)
v2 := v1.xyz           // Get vec3(1, 2, 3) and initialize v2 with this.
v2.xyz = v2.xxx        // Get vec3(1, 1, 1), and set it to all the components to v2.
                       // Then, v2 is now (1, 1, 1).

每个组件如下所示。可以将它们混合在同一组中,但不能在不同组中混合。例如,.xxyy.abgr可用,但.xxgg无效。

  • xyz,w
  • rgb,a
  • stp,q

统一变量

统一变量是一个全局变量,其值在外部给出。无论像素的位置如何,该值都是相同的。

在 Kage 中,uniform 变量是以大写开头的全局变量(即导出变量)。

不能在 Kage 中为统一变量赋值。

不能在 Kage 中定义除统一变量之外的其他全局变量。

内置函数 (Go)

功能 描述
cap(x T) int T是数组类型。返回数组的长度。(v2.1.0)
len(x T) int T是数组类型。返回数组的长度。

内置函数(数学)

大多数内置函数都是通用的。T表示floatvec2,vec3vec4除非另有说明。当类型为向量时,该函数适用于每个组件。

2021SC@SDUSC Ebiten(三) 着色器代码详解_第1张图片

2021SC@SDUSC Ebiten(三) 着色器代码详解_第2张图片 

内置函数(图像)

功能 描述
imageSrcNAt(pos vec2) vec4 返回源图像N 的纹素中vec4给定位置pos的颜色值。N为 0 到 3。
imageSrcNUnsafeAt(pos vec2) vec4 返回源图像N 的纹素中vec4给定位置pos的颜色值。N为 0 到 3。与安全版本 (imageSrcNAt )的区别在于位置越界时的返回值。在这种情况下,安全版本返回 vec4(0),而不安全版本的返回值未定义。不安全的版本更快。如果您确定位置在边界内,则可以使用不安全版本来提高性能。
imageSrcTextureSize() vec2 以像素为单位返回源图像的纹理大小
imageDstTextureSize() vec2 以像素为单位返回目标图像的纹理大小
imageSrcRegionOnTexture() (vec2, vec2) 以 texels 为单位返回源图像的原点位置和纹理上的大小
imageDstRegionOnTexture() (vec2, vec2) 返回目标图像的原点位置和纹理大小(以 texels 为单位)(v2.1.0)

纹理和图像

Ebiten 的图像 ( ebiten.Image) 实际上是内部纹理的一部分。然后,着色器中的位置计算有点复杂。

像素是一个颜色点的单位。另一方面,texel 是一个覆盖整个区域的单位,值在 0 到 1 之间。 texel 的含义取决于纹理,因此不能将不同纹理的 texel 混合在一起。

要相互转换像素和纹素,可以使用这些公式。

 2021SC@SDUSC Ebiten(三) 着色器代码详解_第3张图片

 

你可能感兴趣的:(Ebiten,1024程序员节,go,着色器,go语言)