Godot 4 着色器 - Shader调试

Godot实现蝴蝶飞舞Shader 学习到了一些基础的Shader知识,明白了纯Shader只能处理一些简单的操作,想这种比较复杂的3D效果最好采用3D粒子的方式实现。 阅读详情

我之前用OpenCV进行图像相关处理,觉得已经很不错,结合GDI可以实现流畅的动画效果

直到近来用Shader后才发现,着色器更上一层楼,原来这是入了GPU的坑

Shader编程限制很多,各种不支持,看在它性能不错功能炫酷的份上,忍了,努力增加一些自己需要的功能

最优先的功能是调试需要,Shader的过程信息也不能输出到文本日志中,也不能输出到调试窗口中。查了一下,一般的做法就是在画面中用一些颜色表示。这应该是比较低效的了。

琢磨了一下,调试信息还是只能在画面上显示,不过信息最好能以图形、文字等形式展现

图形信息展示

一般来说,能在画面上把点、线、矩形、圆展示出来就OK,当然,点可以通过圆画出来。

先来最简单的线。主要的几个参数:

uv: UV坐标系的点,当前像素点坐标,归一化表示

firstPoint、secondPoint:线段的两点

lineWidth:线宽

startColor、endColor:计划实现渐变的颜色填充,这是填充的首尾色

gradientMethod:渐变模式,水平/垂直/中心辐射

// 【图形信息】在指定位置(两点式+线宽)画出线段
vec4 metaLog_Line(vec2 uv, vec2 firstPoint, vec2 secondPoint, float lineWidth, vec4 startColor, vec4 endColor, int gradientMethod, out bool inFlag) {
	float distance = distancePointToLine(uv, firstPoint, secondPoint) / lineWidth;
	inFlag = (distance < 0.5 && 
		(length(uv - (firstPoint + secondPoint) / 2.0) <= length(firstPoint - secondPoint) / 2.0));
	if(inFlag) {
		float startDistance, endDistance;
		if((gradientMethod & DIR_VERT) == 0) {
			startDistance = length(uv - firstPoint);
			endDistance = length(uv - secondPoint);
		} else {
			bool atRightFlag = false; 
			if(firstPoint.x == secondPoint.x)
				atRightFlag = uv.x >= firstPoint.x;
			else {
				float m = (secondPoint.y - firstPoint.y) / (secondPoint.x - firstPoint.x);
				float v = uv.y - m * (uv.x - firstPoint.x) - firstPoint.y;
				atRightFlag = (v >= 0.0);
			}
			endDistance = atRightFlag ? 0.5 - distance : .5 + distance;
			startDistance = atRightFlag ? 0.5 + distance : 0.5 - distance;
		}
		float startWeight = 1.0 - startDistance / (startDistance + endDistance);
		if((gradientMethod & GRADIENT_MIDDLE) > 0)
			startWeight = abs(startDistance - endDistance);
		return startColor* startWeight + endColor * (1.0 - startWeight);
	}
	return vec4(0);
}

核心思路就是判断uv是否在指定线宽的线段上(决定输出的inFlag),如果在其上就根据填充方式与uv位置、两点位置计算出颜色融合权重,并据此算出最终颜色值。如果不在其上就不受影响。

则调试时加入相应调用即可,如在翻页时,展示出鼠标所在位置与相应基准角点连线

loggedColor = metaLog_Line(uv, mousePoint / pageSize, basePoint / pageSize, 0.002, vec4(1.0, 0.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), DIR_HORZ, inFlag, !WHOLE_LINE);
if(inFlag) color = loggedColor;			

 运行效果如下

 确认能达到调试效果。剩下的矩形、圆就轻松了。

// 【图形信息】在指定位置(p1、p2)画出矩形,
vec4 metaLog_Rect(vec2 uv, vec2 p1, vec2 p2, vec4 startColor, vec4 endColor, int gradientMethod, out bool inFlag) {
	vec2 leftTopPoint = vec2(min(p1.x, p2.x), min(p1.y, p2.y));
	vec2 rightBottomPoint = vec2(max(p1.x, p2.x), max(p1.y, p2.y));
	inFlag = isInRange(uv.x, leftTopPoint.x, rightBottomPoint.x) &&
	   		 isInRange(uv.y, leftTopPoint.y, rightBottomPoint.y);
	if(inFlag) {
		float startDistance, endDistance;
		if((gradientMethod & DIR_VERT) == 0) {
			startDistance = (uv.x - leftTopPoint.x);
			endDistance = (rightBottomPoint.x - uv.x);
		} else {
			startDistance = (uv.y - leftTopPoint.y);
			endDistance = (rightBottomPoint.y - uv.y);
		}
		float startWeight = 1.0 - startDistance / (startDistance + endDistance);
		if((gradientMethod & GRADIENT_MIDDLE) > 0)
			startWeight = abs(startDistance - endDistance);
		return startColor * startWeight + endColor * (1.0 - startWeight);
	}
	return vec4(0); 
}

// 【图形信息】在指定位置(圆心+半径)画出圆
vec4 metaLog_Circle(vec2 uv, vec2 centerPoint, float radius, vec4 startColor, vec4 endColor, int gradientMethod, out bool inFlag) {
	float distance = length(uv - centerPoint);
	inFlag = distance <= radius;
	if(inFlag) {
		float startWeight = 0.0;
		if( (gradientMethod & DIR_ZOOMIN) > 0 )
			startWeight = 1.0 - distance / radius;;
		if( (gradientMethod & DIR_ZOOMOUT) > 0)
			startWeight = distance / radius;
		return startColor * startWeight + endColor * (1.0 - startWeight);
	}
	return vec4(0);
}

思路差不多,根据当前像素点位置、待显示图形参数与渐变颜色,确定最终的颜色。

比如,折页碰到中间限制后,目标点就不能再为鼠标点了,需要调整,看起来才合理自然。

// 调整后的mousePoint输出显示
loggedColor = metaLog_Circle(uv, mousePoint / pageSize, 0.01, logFontColor, endColor, DIR_ZOOMIN, inFlag);
if(inFlag) color = loggedColor;

在此思路基础上 ,想用任何图形信息调试均可较轻松实现。

 文字输出

文字输出,本质上也是画出来,所以,首先要自己做一个字模。

做字模也简单,先确认目标,32*32的位图即可。其次是范围,中文太多肯定不用,就把可打印的ASCII字符做出来。之后用Word用某种喜欢的字体把这些字符录入,缩放到合适比例大小,确保可以截下来的每个字符图片均为32*32

花了一点时间,生成所需要的ASCII字符图片

 然后针对各图片逐行扫描,生成01码,每行32位,刚好一个int表示,这样一个字模用32个int表示。解析的C++代码:

TStrings * fileNames = new TStringList;
TStrings * results = new TStringList;
THelper::File::BrowseDir(fileNames, path, L"*.bmp", false);
for(int index = 0; index < fileNames->Count; ++index) {
	UnicodeString fileName = fileNames->Strings[index];
	cv::Mat mat = CvHelper::MatFromFile(fileName);
	mat = CvHelper::ToMat_GRAY(mat);
	threshold(mat, mat, 128, 255, cv::THRESH_BINARY);
	int v[32];
	UnicodeString valueInfo = L"";
	for(int row = 0; row < mat.rows; ++row) {
		int value = 0;
		UnicodeString s = L"";
		for(int col = 0; col < mat.cols; ++col) {
			value <<= 1;
			BYTE data = mat.at<BYTE>(row, col);
			if(data == 0)
				value += 1;
			s += data == 0 ? L"*" : L" ";
		}
		v[row] = value;
		THelper::Logi(L"%s > 0x%X", s, value);
		if(row)
			valueInfo += L", ";
		valueInfo += FORMAT(L"0x%X", value);
	}

	results->Add(FORMAT(L"if(asciiChar == 0x%02X) model.Model = int[](%s);",
		TTypeConvert::String2Int(THelper::File::ExtractPureFileName(fileName)), valueInfo));
}
THelper::Logi(L"result:\n%s", TTypeConvert::StringList2String(results, L"\n"));
delete results;
delete fileNames;

从而生成Shader可用字模代码:

int Model[32];
	 if(asciiChar == 0x21) Model = int[](0x0, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x3C000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x0, 0x0, 0x0, 0x0, 0x7C000, 0xFE000, 0xFE000, 0xFE000, 0xFE000, 0x7C000, 0x38000, 0x0);
else if(asciiChar == 0x22) Model = int[](0x0, 0x381C00, 0x7C3E00, 0xFE7F00, 0xFE7F00, 0xFE3F00, 0x7E3F00, 0xE0700, 0xE0700, 0x1C0E00, 0x1C0E00, 0x381C00, 0xF07C00, 0xE07000, 0x402000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x23) Model = int[](0x0, 0x0, 0xE0E00, 0xC0E00, 0xC0E00, 0x1C0C00, 0x1C0C00, 0x1C1C00, 0x1C1C00, 0x1C1C00, 0x1FFFF80, 0x1FFFF80, 0x1FFFF80, 0x381800, 0x381800, 0x383800, 0x383800, 0x383800, 0x383800, 0x3FFFF80, 0x3FFFF80, 0x3FFFF00, 0x703000, 0x707000, 0x707000, 0x707000, 0x707000, 0x707000, 0x607000, 0xE07000, 0x606000, 0x0);
else if(asciiChar == 0x24) Model = int[](0x0, 0x18000, 0x18000, 0x18000, 0x18000, 0x1C000, 0xFF000, 0x1FFC00, 0x3FFE00, 0x780C00, 0x780000, 0x780000, 0x780000, 0x3E0000, 0x3F8000, 0x1FF000, 0x7F800, 0xFC00, 0x3E00, 0x1F00, 0xF00, 0xF00, 0x700E00, 0xFC3E00, 0x7FFC00, 0x1FF800, 0x3C000, 0x18000, 0x18000, 0x18000, 0x18000, 0x18000);
else if(asciiChar == 0x25) Model = int[](0x0, 0x0, 0xF80000, 0x1FE0040, 0x3CF00E0, 0x38701E0, 0x70703C0, 0x7038380, 0x7038700, 0x7038E00, 0x7039C00, 0x7871800, 0x38F0000, 0x1FE0000, 0x1FC0000, 0x300000, 0x3F80, 0x7FC0, 0xC71E0, 0x1CE0E0, 0x38E0E0, 0x70E0F0, 0xE0E0F0, 0x1E0E0E0, 0x3C0E0E0, 0x780F0E0, 0x30079E0, 0x3FC0, 0x1F00, 0x0, 0x0, 0x0);
else if(asciiChar == 0x26) Model = int[](0x0, 0x0, 0x1F0000, 0x3FC000, 0x7FE000, 0x70E000, 0xF0E000, 0xE0E000, 0xE0E000, 0xE0E000, 0xF1C000, 0xF3C000, 0x7F8000, 0x7F0000, 0x7C01C0, 0xFC01C0, 0x1FE03C0, 0x3FF03C0, 0x3CF8780, 0x787C780, 0x783EF00, 0x781FF00, 0x780FE00, 0x7807E00, 0x7C07F00, 0x3E0FFC0, 0x1FFFFE0, 0xFFE3C0, 0x7F80C0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x27) Model = int[](0x0, 0x3C000, 0x3E000, 0x7E000, 0x7E000, 0x3F000, 0x1F000, 0x6000, 0xE000, 0xE000, 0x1C000, 0x3C000, 0x78000, 0x20000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x28) Model = int[](0x1000, 0x7800, 0x7000, 0xE000, 0x1C000, 0x1C000, 0x38000, 0x38000, 0x70000, 0x70000, 0x60000, 0xE0000, 0xE0000, 0xE0000, 0xE0000, 0xE0000, 0xE0000, 0xE0000, 0xE0000, 0xE0000, 0x60000, 0x70000, 0x70000, 0x78000, 0x38000, 0x3C000, 0x1C000, 0xE000, 0x7000, 0x7800, 0x1000, 0x0);
else if(asciiChar == 0x29) Model = int[](0x40000, 0xF0000, 0x70000, 0x38000, 0x1C000, 0x1C000, 0xE000, 0xF000, 0x7000, 0x7000, 0x3000, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3000, 0x7000, 0x7000, 0xE000, 0xE000, 0x1C000, 0x1C000, 0x38000, 0x70000, 0xF0000, 0x40000, 0x0);
else if(asciiChar == 0x2A) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x41C100, 0xF9CF80, 0x7FFF00, 0x1FFC00, 0x7E000, 0x3E000, 0x7F000, 0xF7800, 0xE3800, 0x1C1C00, 0x380C00, 0x180C00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x2B) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1FFFFC0, 0x1FFFFC0, 0x1FFFFC0, 0x3C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x2C) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C000, 0x7E000, 0x7E000, 0x7E000, 0x7F000, 0x3F000, 0xF000, 0xE000, 0xE000, 0x1E000, 0x3C000, 0xF8000, 0xF0000, 0x40000);
else if(asciiChar == 0x2D) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3FFFFF0, 0x3FFFFF0, 0x3FFFFF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x2E) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C000, 0x7E000, 0x7E000, 0x7F000, 0x7E000, 0x3E000, 0x1C000, 0x0);
else if(asciiChar == 0x2F) Model = int[](0x700, 0xE00, 0xE00, 0x1E00, 0x1C00, 0x1C00, 0x3800, 0x3800, 0x3800, 0x7000, 0x7000, 0xF000, 0xE000, 0xE000, 0x1C000, 0x1C000, 0x1C000, 0x38000, 0x38000, 0x78000, 0x70000, 0x70000, 0xE0000, 0xE0000, 0xE0000, 0x1C0000, 0x1C0000, 0x3C0000, 0x380000, 0x380000, 0x700000, 0x0);
else if(asciiChar == 0x30) Model = int[](0x18000, 0x1FF800, 0x3FFC00, 0x7FFE00, 0xFC3F00, 0x1F80F80, 0x1F00780, 0x3E007C0, 0x3E003C0, 0x3C003C0, 0x3C003E0, 0x7C003E0, 0x7C081E0, 0x7C3C1E0, 0x7C7E1E0, 0x787E1E0, 0x787E1E0, 0x7C7E1E0, 0x7C3C1E0, 0x7C001E0, 0x7C003E0, 0x3C003E0, 0x3C003C0, 0x3E003C0, 0x3E007C0, 0x1F00780, 0x1F80F80, 0xFC3F00, 0x7FFE00, 0x3FFC00, 0x1FF800, 0x1C000);
else if(asciiChar == 0x31) Model = int[](0x0, 0x1F000, 0x7F000, 0xFFF000, 0xFFF000, 0xFFF000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1F000, 0x1FFFFE0, 0x3FFFFE0, 0x3FFFFE0, 0x3FFFFE0, 0x0);
else if(asciiChar == 0x32) Model = int[](0x30000, 0x3FF000, 0xFFFC00, 0x1FFFE00, 0x3F87F00, 0x7C01F00, 0x3800F80, 0xF80, 0xF80, 0x780, 0x780, 0xF80, 0xF80, 0xF00, 0x1F00, 0x3E00, 0x7C00, 0x7C00, 0xF800, 0x1F000, 0x3E000, 0x7C000, 0xF8000, 0x1F0000, 0x7E0000, 0xFC0000, 0x1F80000, 0x3FFFFE0, 0x7FFFFE0, 0x7FFFFE0, 0x7FFFFE0, 0x0);
else if(asciiChar == 0x33) Model = int[](0x38000, 0x3FF800, 0xFFFE00, 0x1FFFF00, 0x3F87F00, 0x1E01F80, 0x1800F80, 0x780, 0x7C0, 0x780, 0xF80, 0xF80, 0x3F00, 0x1FE00, 0x1FF800, 0x1FF000, 0x1FFC00, 0x1FF00, 0x1F80, 0xFC0, 0x7C0, 0x3C0, 0x3E0, 0x3E0, 0x7C0, 0x30007C0, 0x7C00FC0, 0x7F87F80, 0x3FFFF00, 0x1FFFE00, 0x7FF800, 0x78000);
else if(asciiChar == 0x34) Model = int[](0x0, 0x3E00, 0x7E00, 0xFE00, 0x1FE00, 0x1FE00, 0x3DE00, 0x7DE00, 0xF9E00, 0xF1E00, 0x1F1E00, 0x3E1E00, 0x7C1E00, 0x781E00, 0xF81E00, 0x1F01E00, 0x3E01E00, 0x3C01E00, 0x7801E00, 0xFFFFFE0, 0xFFFFFF0, 0xFFFFFF0, 0xFFFFFF0, 0x1E00, 0x1E00, 0x1E00, 0x1E00, 0x1E00, 0x1E00, 0x1E00, 0x1E00, 0x0);
else if(asciiChar == 0x35) Model = int[](0x0, 0xFFFF80, 0xFFFF80, 0xFFFF80, 0xFFFF80, 0xF00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1E00000, 0x1E7F000, 0x1FFFE00, 0x1FFFF00, 0x1FCFF80, 0xE01FC0, 0xFC0, 0x7C0, 0x3E0, 0x3E0, 0x3E0, 0x3E0, 0x3C0, 0x7C0, 0x3000FC0, 0x7C01F80, 0x7F07F80, 0x3FFFF00, 0x1FFFC00, 0x7FF800, 0x78000);
else if(asciiChar == 0x36) Model = int[](0x6000, 0x7FE00, 0x1FFF80, 0x3FFFC0, 0x7F8FC0, 0xFC0180, 0xF80000, 0x1F00000, 0x1E00000, 0x3E00000, 0x3E00000, 0x3C00000, 0x3C00000, 0x3C3FE00, 0x7CFFF00, 0x7DFFF80, 0x7FE0FC0, 0x7F007C0, 0x7E003E0, 0x3C003E0, 0x3C001E0, 0x3C001E0, 0x3C001E0, 0x3E001E0, 0x1E003E0, 0x1F003E0, 0xF807C0, 0xFE1FC0, 0x7FFF80, 0x3FFE00, 0xFFC00, 0x1C000);
else if(asciiChar == 0x37) Model = int[](0x0, 0x7FFFFE0, 0x7FFFFE0, 0x7FFFFE0, 0x7FFFFE0, 0x7C0, 0x780, 0xF00, 0x1F00, 0x1E00, 0x3C00, 0x7C00, 0x7800, 0xF800, 0xF000, 0x1F000, 0x1E000, 0x1E000, 0x3E000, 0x3C000, 0x3C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x78000, 0x78000, 0xF8000, 0xF8000, 0xF8000, 0xF8000, 0x0);
else if(asciiChar == 0x38) Model = int[](0x1C000, 0x1FF800, 0x3FFE00, 0x7FFF00, 0xFC1F80, 0x1F00F80, 0x1E007C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1F00380, 0x1F80780, 0xFC0F00, 0x7F1F00, 0x3FFE00, 0x1FFC00, 0x3FFE00, 0xF8FF00, 0x1F01F80, 0x3E00FC0, 0x3C007E0, 0x78003E0, 0x78001E0, 0x78001E0, 0x7C001E0, 0x7C003E0, 0x3E007C0, 0x3F80FC0, 0x1FFFF80, 0xFFFF00, 0x3FFC00, 0x3C000);
else if(asciiChar == 0x39) Model = int[](0x30000, 0x3FF000, 0x7FFC00, 0xFFFE00, 0x1F83F00, 0x3E01F00, 0x3E00F80, 0x7C007C0, 0x7C007C0, 0x78003C0, 0x78003C0, 0x78003E0, 0x7C003E0, 0x7C007E0, 0x3E00FE0, 0x3F03FE0, 0x1FFFFE0, 0xFFF3E0, 0x7FE3E0, 0x603E0, 0x3C0, 0x3C0, 0x7C0, 0x780, 0xF80, 0x1F80, 0x1C03F00, 0x3F0FE00, 0x3FFFC00, 0x1FFF800, 0x7FE000, 0xF0000);
else if(asciiChar == 0x3A) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C000, 0x3E000, 0x7F000, 0x7F000, 0x7F000, 0x3E000, 0x3C000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C000, 0x3E000, 0x7F000, 0x7F000, 0x7F000, 0x7E000, 0x3E000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x3B) Model = int[](0x0, 0x0, 0x0, 0x3C000, 0x7E000, 0x7E000, 0x7E000, 0x7E000, 0x7C000, 0x18000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C000, 0x7E000, 0x7E000, 0x7F000, 0x7F000, 0x1F000, 0xE000, 0xE000, 0xE000, 0x1C000, 0x3C000, 0xF8000, 0xE0000, 0x0, 0x0, 0x0);
else if(asciiChar == 0x3C) Model = int[](0x0, 0x0, 0x0, 0x0, 0x200, 0x600, 0x1E00, 0x3E00, 0xFC00, 0x1F000, 0x7E000, 0xF8000, 0x3F0000, 0x7C0000, 0xF80000, 0xF00000, 0xF80000, 0x7C0000, 0x3F0000, 0xF8000, 0x7E000, 0x1F000, 0xFC00, 0x3E00, 0x1E00, 0x600, 0x200, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x3D) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3FFFFF0, 0x3FFFFF0, 0x3FFFFF0, 0x3FFFFF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3FFFFF0, 0x3FFFFF0, 0x3FFFFF0, 0x3FFFFF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x3E) Model = int[](0x0, 0x0, 0x0, 0x0, 0x400000, 0x600000, 0x780000, 0x7C0000, 0x3F0000, 0xF8000, 0x7E000, 0x1F000, 0xFC00, 0x3E00, 0x1F00, 0xF00, 0x1F00, 0x3E00, 0xFC00, 0x1F000, 0x7E000, 0xF8000, 0x3F0000, 0x7C0000, 0x780000, 0x600000, 0x400000, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x3F) Model = int[](0x0, 0x0, 0x0, 0x7E000, 0x1FF800, 0x3FFC00, 0x7C3E00, 0x301E00, 0xE00, 0xE00, 0x1E00, 0x1E00, 0x3C00, 0x7800, 0xF000, 0x1E000, 0x3C000, 0x3C000, 0x38000, 0x38000, 0x0, 0x0, 0x0, 0x3C000, 0x7C000, 0x7E000, 0x7E000, 0x7E000, 0x3C000, 0x0, 0x0, 0x0);
else if(asciiChar == 0x40) Model = int[](0x0, 0x3F000, 0xFFC00, 0x3F3E00, 0x780700, 0x700700, 0xE00380, 0xE00380, 0x1C00380, 0x1C00180, 0x1800780, 0x3807F80, 0x381FF80, 0x383E380, 0x3878380, 0x3870380, 0x3870380, 0x3870380, 0x3870780, 0x387FF80, 0x383F980, 0x180E000, 0x1C00000, 0x1C00000, 0xE00000, 0xF00000, 0x700000, 0x3C0600, 0x1FFF00, 0xFFC00, 0x1F000, 0x0);
else if(asciiChar == 0x41) Model = int[](0x0, 0x0, 0xFC000, 0xFC000, 0xFC000, 0x1FE000, 0x1DE000, 0x1DE000, 0x3CF000, 0x3CF000, 0x38F000, 0x787800, 0x787800, 0x707800, 0xF07C00, 0xF03C00, 0xF03C00, 0x1E03E00, 0x1FFFE00, 0x1FFFE00, 0x3FFFF00, 0x3FFFF00, 0x3C00F00, 0x7800F80, 0x7800F80, 0x7800780, 0xF8007C0, 0xF0007C0, 0xF0003C0, 0x1F0003E0, 0x0, 0x0);
else if(asciiChar == 0x42) Model = int[](0x0, 0x7FFE000, 0x7FFF800, 0x7FFFE00, 0x7FFFE00, 0x7C03F00, 0x7C01F00, 0x7C00F00, 0x7C00F80, 0x7C00F00, 0x7C00F00, 0x7C01F00, 0x7C03E00, 0x7FFFC00, 0x7FFF800, 0x7FFF800, 0x7FFFE00, 0x7C07F00, 0x7C00F80, 0x7C007C0, 0x7C007C0, 0x7C003C0, 0x7C003C0, 0x7C007C0, 0x7C007C0, 0x7C00FC0, 0x7C01F80, 0x7FFFF80, 0x7FFFF00, 0x7FFFC00, 0x7FFF000, 0x0);
else if(asciiChar == 0x43) Model = int[](0x1FC00, 0xFFF00, 0x1FFFC0, 0x7FFFE0, 0x7F07E0, 0xFC01C0, 0x1F80000, 0x1F00000, 0x3E00000, 0x3E00000, 0x3C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x3E00000, 0x3E00000, 0x3F00000, 0x1F80040, 0xFC00E0, 0xFE03E0, 0x7FFFE0, 0x3FFFC0, 0xFFF80, 0x3FE00, 0x0);
else if(asciiChar == 0x44) Model = int[](0x0, 0x7FF8000, 0x7FFF000, 0x7FFFC00, 0x7FFFE00, 0x7C07F00, 0x7C03F00, 0x7C01F80, 0x7C00FC0, 0x7C007C0, 0x7C007C0, 0x7C003C0, 0x7C003E0, 0x7C003E0, 0x7C003E0, 0x7C003E0, 0x7C003E0, 0x7C003E0, 0x7C003E0, 0x7C003E0, 0x7C007C0, 0x7C007C0, 0x7C007C0, 0x7C00F80, 0x7C01F80, 0x7C03F00, 0x7C07F00, 0x7FFFE00, 0x7FFFC00, 0x7FFF000, 0x7FFC000, 0x0);
else if(asciiChar == 0x45) Model = int[](0x0, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3FFFC00, 0x3FFFE00, 0x3FFFE00, 0x3FFFE00, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x0);
else if(asciiChar == 0x46) Model = int[](0x0, 0x1FFFFC0, 0x1FFFFC0, 0x1FFFFC0, 0x1FFFFC0, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1FFFF00, 0x1FFFF00, 0x1FFFF00, 0x1FFFF00, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x0);
else if(asciiChar == 0x47) Model = int[](0x1FC00, 0xFFF00, 0x1FFFC0, 0x7FFFE0, 0xFF07C0, 0xFC0180, 0x1F80000, 0x1F00000, 0x3E00000, 0x3E00000, 0x3C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C00000, 0x7C07FE0, 0x7C07FE0, 0x7C07FE0, 0x7C03FE0, 0x7C001E0, 0x7C001E0, 0x3E001E0, 0x3E001E0, 0x3F001E0, 0x1F001E0, 0x1F801E0, 0xFE03E0, 0x7FFFE0, 0x3FFFC0, 0x1FFF80, 0x3FE00, 0x0);
else if(asciiChar == 0x48) Model = int[](0x0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3FFFFE0, 0x3FFFFE0, 0x3FFFFE0, 0x3FFFFE0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x0);
else if(asciiChar == 0x49) Model = int[](0x0, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x0);
else if(asciiChar == 0x4A) Model = int[](0x0, 0xFFFFC0, 0xFFFFC0, 0xFFFFC0, 0x7FFFC0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x780, 0x800F80, 0x1C00F80, 0x3E01F80, 0x1F87F00, 0x1FFFE00, 0xFFFE00, 0x3FF800, 0x7C000);
else if(asciiChar == 0x4B) Model = int[](0x0, 0x7C007C0, 0x7C00FC0, 0x7C01F80, 0x7C01F00, 0x7C03E00, 0x7C07C00, 0x7C0F800, 0x7C1F800, 0x7C3F000, 0x7C3E000, 0x7C7C000, 0x7CF8000, 0x7DFC000, 0x7FFC000, 0x7FFE000, 0x7FFF000, 0x7F9F000, 0x7F0F800, 0x7F0F800, 0x7E07C00, 0x7C07C00, 0x7C03E00, 0x7C03E00, 0x7C01F00, 0x7C01F80, 0x7C00F80, 0x7C007C0, 0x7C007C0, 0x7C003E0, 0x7C003E0, 0x0);
else if(asciiChar == 0x4C) Model = int[](0x0, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0x0);
else if(asciiChar == 0x4D) Model = int[](0x0, 0x7E007C0, 0x7E007C0, 0x7E00FC0, 0x7E00FC0, 0x7F00FC0, 0x7F01FC0, 0x7F01FC0, 0x7F81DC0, 0x7B83DC0, 0x7B83BC0, 0x7BC3BC0, 0x7BC7BC0, 0x79C73C0, 0x79E73C0, 0x79EF3C0, 0x78EE3C0, 0x78FE3C0, 0x78FE3C0, 0x787C3C0, 0x787C3C0, 0x783C3C0, 0x78383C0, 0x78003C0, 0x78003C0, 0x78003C0, 0x78003C0, 0x78003C0, 0x78003C0, 0x78003C0, 0x78003C0, 0x0);
else if(asciiChar == 0x4E) Model = int[](0x0, 0x3E003C0, 0x3F003C0, 0x3F003C0, 0x3F803C0, 0x3F803C0, 0x3FC03C0, 0x3FC03C0, 0x3DE03C0, 0x3DE03C0, 0x3DF03C0, 0x3CF03C0, 0x3CF83C0, 0x3C783C0, 0x3C7C3C0, 0x3C3C3C0, 0x3C3E3C0, 0x3C1E3C0, 0x3C1F3C0, 0x3C0F3C0, 0x3C0F3C0, 0x3C07BC0, 0x3C07BC0, 0x3C03FC0, 0x3C03FC0, 0x3C01FC0, 0x3C01FC0, 0x3C00FC0, 0x3C00FC0, 0x3C007C0, 0x3C007C0, 0x0);
else if(asciiChar == 0x4F) Model = int[](0xFE000, 0x3FF800, 0x7FFE00, 0xFFFF00, 0x1FC3F00, 0x3F01F80, 0x3E00FC0, 0x7C007C0, 0x7C007C0, 0x7C003E0, 0xF8003E0, 0xF8003E0, 0xF8001E0, 0xF8001E0, 0xF8001E0, 0xF8001F0, 0xF8001F0, 0xF8001E0, 0xF8001E0, 0xF8003E0, 0xF8003E0, 0x7C003E0, 0x7C003C0, 0x7C007C0, 0x3E00FC0, 0x3F00F80, 0x1F83F80, 0xFFFF00, 0xFFFE00, 0x3FFC00, 0xFF000, 0x0);
else if(asciiChar == 0x51) Model = int[](0xF0000, 0x3FE000, 0xFFF000, 0x1FFF800, 0x1E07C00, 0x3C03C00, 0x3C03C00, 0x7801E00, 0x7801E00, 0x7801E00, 0x7800E00, 0x7800E00, 0x7800F00, 0x7800F00, 0x7800E00, 0x7801E00, 0x7801E00, 0x7801E00, 0x7801E00, 0x3C03C00, 0x3C03C00, 0x1E07800, 0xFFF800, 0x7FF000, 0x3FC000, 0xF0000, 0x78000, 0x3C000, 0x3FE00, 0x1FF00, 0x7F00, 0x0);
else if(asciiChar == 0x52) Model = int[](0x0, 0x7FFF000, 0x7FFFC00, 0x7FFFF00, 0x7FFFF00, 0x7C01F80, 0x7C00F80, 0x7C007C0, 0x7C007C0, 0x7C007C0, 0x7C007C0, 0x7C007C0, 0x7C007C0, 0x7C00F80, 0x7C01F80, 0x7FFFF00, 0x7FFFE00, 0x7FFFC00, 0x7FFF000, 0x7C1F000, 0x7C1F800, 0x7C0F800, 0x7C0FC00, 0x7C07C00, 0x7C03E00, 0x7C03E00, 0x7C01F00, 0x7C01F80, 0x7C00F80, 0x7C00FC0, 0x7C007C0, 0x7C003E0);
else if(asciiChar == 0x53) Model = int[](0x7F000, 0x3FFE00, 0x7FFF80, 0xFFFFC0, 0x1FC0F80, 0x1F00380, 0x1E00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x1F00000, 0x1FC0000, 0xFF0000, 0xFFC000, 0x3FF800, 0x1FFE00, 0x3FF00, 0xFF80, 0x3FC0, 0xFE0, 0x7E0, 0x3E0, 0x3E0, 0x3E0, 0x18003E0, 0x3C007C0, 0x7F00FC0, 0x3FFFF80, 0x1FFFF00, 0x7FFE00, 0x1FF800, 0x0);
else if(asciiChar == 0x54) Model = int[](0x0, 0xFFFFFF8, 0xFFFFFF8, 0xFFFFFF8, 0xFFFFFF8, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3C000);
else if(asciiChar == 0x55) Model = int[](0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C003C0, 0x7C007C0, 0x7C007C0, 0x7C007C0, 0x3E00780, 0x3F00F80, 0x3F83F80, 0x1FFFF00, 0xFFFE00, 0x7FFC00, 0x1FF000, 0x0);
else if(asciiChar == 0x56) Model = int[](0x0, 0xF8000F8, 0xF8000F0, 0x7C001F0, 0x7C001F0, 0x7C001E0, 0x3E001E0, 0x3E003E0, 0x3E003E0, 0x1E003C0, 0x1F007C0, 0x1F007C0, 0xF00780, 0xF80780, 0xF80F80, 0x780F00, 0x7C0F00, 0x7C1F00, 0x7C1E00, 0x3C1E00, 0x3E1E00, 0x3E3C00, 0x1E3C00, 0x1E3C00, 0x1F7C00, 0xF7800, 0xF7800, 0xFF800, 0x7F000, 0x7F000, 0x7F000, 0x3E000);
else if(asciiChar == 0x57) Model = int[](0x0, 0x3E0000F8, 0x3E0000F8, 0x3E0000F8, 0x3F0000F8, 0x1F0000F8, 0x1F0000F8, 0x1F0000F8, 0x1F0000F0, 0x1F03C0F0, 0x1F03C0F0, 0xF07E1F0, 0xF07E1F0, 0xF07E1F0, 0xF8FE1F0, 0xF8FF1E0, 0xF8EF1E0, 0xF8EF1E0, 0x79EF1E0, 0x79E79E0, 0x79E79E0, 0x79C7BE0, 0x7BC7BC0, 0x7BC3BC0, 0x7BC3FC0, 0x3F83FC0, 0x3F83FC0, 0x3F81FC0, 0x3F81FC0, 0x3F01F80, 0x3F01F80, 0x3F01F80);
else if(asciiChar == 0x58) Model = int[](0x0, 0x7C003E0, 0x7E007C0, 0x3E007C0, 0x1F00F80, 0x1F00F00, 0xF81F00, 0xF81E00, 0x7C3E00, 0x7C3C00, 0x3E7C00, 0x1E7800, 0x1FF000, 0xFF000, 0xFE000, 0x7E000, 0xFE000, 0xFF000, 0x1FF000, 0x1EF800, 0x3EF800, 0x7C7C00, 0x7C3C00, 0xF83E00, 0xF01F00, 0x1F01F00, 0x1E00F80, 0x3E00F80, 0x7C007C0, 0x7C007E0, 0xF8003E0, 0x0);
else if(asciiChar == 0x59) Model = int[](0x0, 0xF8000F0, 0x7C001F0, 0x7C001E0, 0x3E003E0, 0x3E003C0, 0x1F007C0, 0x1F00780, 0xF80F80, 0xF80F00, 0x7C1F00, 0x7C1E00, 0x3C3E00, 0x3E3C00, 0x1E7C00, 0x1F7800, 0xFF800, 0xFF000, 0x7F000, 0x7E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x3E000, 0x0);
else if(asciiChar == 0x5A) Model = int[](0x0, 0x3FFFFE0, 0x3FFFFE0, 0x3FFFFE0, 0x3FFFFC0, 0x7C0, 0xF80, 0x1F00, 0x1F00, 0x3E00, 0x7C00, 0xFC00, 0xF800, 0x1F000, 0x3E000, 0x3E000, 0x7C000, 0xF8000, 0xF8000, 0x1F0000, 0x3E0000, 0x3E0000, 0x7C0000, 0xF80000, 0xF80000, 0x1F00000, 0x3E00000, 0x3FFFFE0, 0x7FFFFE0, 0x7FFFFE0, 0x7FFFFE0, 0x0);
else if(asciiChar == 0x5B) Model = int[](0x0, 0x1FF800, 0x1FF800, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1C0000, 0x1FF800, 0x1FF800);
else if(asciiChar == 0x5C) Model = int[](0x0, 0x700000, 0x380000, 0x380000, 0x3C0000, 0x1C0000, 0x1C0000, 0xE0000, 0xE0000, 0xF0000, 0x70000, 0x70000, 0x78000, 0x38000, 0x3C000, 0x1C000, 0x1C000, 0x1E000, 0xE000, 0xF000, 0x7000, 0x7000, 0x7800, 0x3800, 0x3800, 0x1C00, 0x1C00, 0x1E00, 0xE00, 0xE00, 0x700, 0x0);
else if(asciiChar == 0x5D) Model = int[](0x0, 0x1FF800, 0x1FF800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x1FF800, 0x1FF800);
else if(asciiChar == 0x5E) Model = int[](0x0, 0x1C000, 0x3E000, 0x3E000, 0x7E000, 0x77000, 0x77000, 0xE3800, 0xE3800, 0x1E3800, 0x1C1C00, 0x1C1C00, 0x381E00, 0x380E00, 0x780E00, 0x700700, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x5F) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7FFFFC0, 0x7FFFFC0, 0x7FFFFC0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x60) Model = int[](0x0, 0x60000, 0xF0000, 0x1F8000, 0xFC000, 0x7C000, 0x3E000, 0x1F000, 0xF000, 0x6000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x61) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0xFF000, 0x3FFC00, 0xFFFE00, 0x1FFFF00, 0xE01F00, 0x800F80, 0xF80, 0x780, 0x7F80, 0xFFF80, 0x3FFF80, 0xFF0780, 0x1F80780, 0x1E00780, 0x3C00780, 0x3C00780, 0x3C00F80, 0x3E03F80, 0x3F8FF80, 0x1FFF780, 0xFFE780, 0x3F8380, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x62) Model = int[](0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E1F800, 0x1E7FE00, 0x1FFFF00, 0x1FFFF80, 0x1FC0F80, 0x1F007C0, 0x1E007C0, 0x1E003C0, 0x1E003E0, 0x1E003E0, 0x1E003E0, 0x1E003E0, 0x1E003E0, 0x1E003C0, 0x1E003C0, 0x1E007C0, 0x1F00F80, 0x1F81F80, 0x1FFFF00, 0x1FFFE00, 0x1EFFC00, 0x1C1F000, 0x0);
else if(asciiChar == 0x63) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x3F800, 0x1FFF00, 0x3FFF80, 0x7FFF80, 0xFC0380, 0x1F80000, 0x1F00000, 0x1E00000, 0x3E00000, 0x3E00000, 0x3C00000, 0x3C00000, 0x3E00000, 0x3E00000, 0x3E00000, 0x1F00000, 0x1F80000, 0xFC0380, 0x7F9FC0, 0x3FFF80, 0x1FFF00, 0x7F800, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x64) Model = int[](0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0xFC7C0, 0x1FF7C0, 0x7FFFC0, 0xFFFFC0, 0xF80FC0, 0x1F007C0, 0x1F007C0, 0x3E007C0, 0x3E007C0, 0x3E007C0, 0x3C007C0, 0x3C007C0, 0x3C007C0, 0x3E007C0, 0x3E007C0, 0x1E007C0, 0x1F00FC0, 0x1F81FC0, 0xFFFFC0, 0x7FFBC0, 0x3FF3C0, 0xFC180, 0x0);
else if(asciiChar == 0x65) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x3F800, 0x1FFE00, 0x3FFF00, 0x7FBF80, 0xF807C0, 0x1F003C0, 0x1F003C0, 0x1E001E0, 0x3E001E0, 0x3FFFFE0, 0x3FFFFE0, 0x3FFFFE0, 0x3FFFFC0, 0x3E00000, 0x3E00000, 0x1E00000, 0x1F00000, 0xF80000, 0xFE0380, 0x7FFFC0, 0x3FFF80, 0xFFE00, 0xE000, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x66) Model = int[](0x7F80, 0x1FFE0, 0x3FFC0, 0x7F3C0, 0x7C000, 0xF8000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0x3FFFF80, 0x3FFFF80, 0x3FFFF80, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0x0);
else if(asciiChar == 0x67) Model = int[](0x1FFFC0, 0x7FFFC0, 0xFFFFC0, 0x1F87FC0, 0x1E03C00, 0x3E03C00, 0x3C01E00, 0x3C01E00, 0x3C01E00, 0x3E01E00, 0x1E03C00, 0x1F07C00, 0xFFF800, 0xFFF000, 0x1EFC000, 0x1C00000, 0x3C00000, 0x3C00000, 0x3F80000, 0x1FFFF00, 0xFFFFC0, 0x1FFFFC0, 0x3C007C0, 0x78003E0, 0x78003C0, 0x78003C0, 0x78007C0, 0x7E01F80, 0x3FFFF00, 0x1FFFC00, 0x3FE000, 0x0);
else if(asciiChar == 0x68) Model = int[](0x0, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E1FC00, 0x1E3FF00, 0x1EFFF00, 0x1FFFF80, 0x1FC0F80, 0x1F807C0, 0x1F007C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E00380);
else if(asciiChar == 0x69) Model = int[](0x0, 0x3C00, 0x7E00, 0x7E00, 0x7E00, 0x7E00, 0x3C00, 0x0, 0x0, 0x0, 0x0, 0x7FFC00, 0x7FFC00, 0x7FFC00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x1C00);
else if(asciiChar == 0x6A) Model = int[](0x3800, 0x7C00, 0x7C00, 0x7C00, 0x3800, 0x0, 0x0, 0x0, 0x1FF800, 0x1FFC00, 0x1FFC00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3800, 0x3800, 0x7800, 0x1FF000, 0x3FF000, 0xFC000);
else if(asciiChar == 0x6B) Model = int[](0x0, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E00000, 0x1E007C0, 0x1E00F80, 0x1E01F00, 0x1E03E00, 0x1E07C00, 0x1E0F800, 0x1E1F000, 0x1E3E000, 0x1E7C000, 0x1EFE000, 0x1FFF000, 0x1FEF000, 0x1FC7800, 0x1F87C00, 0x1F03E00, 0x1E01E00, 0x1E01F00, 0x1E00F80, 0x1E00780, 0x1E003C0, 0x1E003E0, 0x0);
else if(asciiChar == 0x6C) Model = int[](0x3FFC000, 0x3FFC000, 0x3FFC000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x7C000, 0x3E000, 0x3FFC0, 0x1FFC0, 0xFFC0, 0x7F00, 0x0);
else if(asciiChar == 0x6D) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x71F0F00, 0x73F1FC0, 0x7FFBFC0, 0x7FFFFE0, 0x7E3E3E0, 0x7C3C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x783C1E0, 0x78181C0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x6E) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x1C0FC00, 0x1E3FF00, 0x1EFFF00, 0x1FFFF80, 0x1FC0F80, 0x1F807C0, 0x1F007C0, 0x1E007C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E003C0, 0x1E00380, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x6F) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x7F000, 0x1FFC00, 0x3FFF00, 0x7FFF00, 0xF80F80, 0x1F007C0, 0x1E007C0, 0x3E003E0, 0x3E003E0, 0x3E003E0, 0x3C001E0, 0x3C001E0, 0x3C003E0, 0x3E003E0, 0x3E003E0, 0x1E003C0, 0x1F007C0, 0xF80F80, 0x7F7F80, 0x7FFF00, 0x1FFC00, 0x7F000, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x70) Model = int[](0x0, 0x383F000, 0x3CFFC00, 0x3DFFE00, 0x3FFFF00, 0x3F81F00, 0x3E00F80, 0x3C00F80, 0x3C00780, 0x3C00780, 0x3C007C0, 0x3C007C0, 0x3C007C0, 0x3C007C0, 0x3C00780, 0x3C00780, 0x3C00F80, 0x3E01F00, 0x3F03F00, 0x3FFFE00, 0x3FFFC00, 0x3DFF800, 0x3C7E000, 0x3C00000, 0x3C00000, 0x3C00000, 0x3C00000, 0x3C00000, 0x3C00000, 0x3C00000, 0x3C00000, 0x0);
else if(asciiChar == 0x71) Model = int[](0x0, 0xFC180, 0x1FF3C0, 0x7FFFC0, 0xFFFFC0, 0xF80FC0, 0x1F007C0, 0x1F007C0, 0x3E007C0, 0x3E007C0, 0x3E007C0, 0x3C007C0, 0x3C007C0, 0x3C007C0, 0x3E007C0, 0x3E007C0, 0x1E007C0, 0x1F00FC0, 0x1F81FC0, 0xFFFFC0, 0x7FFFC0, 0x3FF7C0, 0xFC7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x7C0, 0x0);
else if(asciiChar == 0x72) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x1C07F00, 0x1E1FF80, 0x1E3FF80, 0x1E7FF00, 0x1EF8100, 0x1FE0000, 0x1FC0000, 0x1F80000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1F00000, 0x1E00000, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x73) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0xFF000, 0x3FFE00, 0x7FFF00, 0xFC3F00, 0xF00700, 0x1F00000, 0x1F00000, 0x1F00000, 0xFE0000, 0x7FE000, 0x3FFC00, 0xFFF00, 0xFF80, 0x1FC0, 0x7C0, 0x3C0, 0x8003C0, 0x1E007C0, 0x3FC1F80, 0x1FFFF00, 0x7FFE00, 0xFF800, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x74) Model = int[](0x0, 0x0, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0x3FFFFC0, 0x3FFFFC0, 0x3FFFFC0, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF0000, 0xF8000, 0xF8000, 0x7E0C0, 0x7FFC0, 0x3FFE0, 0xFF80, 0x0, 0x0);
else if(asciiChar == 0x75) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1E007C0, 0x1F00FC0, 0x1F01FC0, 0xF83FC0, 0xFFFBC0, 0x7FF3C0, 0x3FC3C0, 0x60000, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x76) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x7C001E0, 0x3C003C0, 0x3C003C0, 0x3E00780, 0x1E00780, 0x1E00780, 0xF00F00, 0xF00F00, 0xF81E00, 0x781E00, 0x781E00, 0x3C3C00, 0x3C3C00, 0x3E3800, 0x1E7800, 0x1E7800, 0xF7000, 0xFF000, 0x7E000, 0x7E000, 0x7E000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x77) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x1E0000F0, 0x1E0000F0, 0xF03C0F0, 0xF07C0F0, 0xF07C1E0, 0xF07C1E0, 0xF07E1E0, 0x78EE1E0, 0x78EE1E0, 0x78EE3C0, 0x78EF3C0, 0x78E73C0, 0x3DC73C0, 0x3DC73C0, 0x3DC7B80, 0x3DC7F80, 0x3FC3F80, 0x1F83F80, 0x1F83F80, 0x1F83F00, 0x1F81F00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x78) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x700E00, 0x381E00, 0x3C3C00, 0x1C3800, 0xE7800, 0xF7000, 0x7E000, 0x3C000, 0x7C000, 0x7E000, 0xEF000, 0x1E7800, 0x3C3800, 0x381C00, 0x781E00, 0xF00F00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x79) Model = int[](0x0, 0x0, 0x0, 0x0, 0x1E00700, 0xE00E00, 0xE00E00, 0x700E00, 0x701C00, 0x781C00, 0x383800, 0x3C3800, 0x1C3800, 0x1C7000, 0xE7000, 0xE6000, 0x7E000, 0x7E000, 0x3C000, 0x3C000, 0x38000, 0x38000, 0x78000, 0xF0000, 0xFE0000, 0xFC0000, 0xF80000, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x7A) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7FFF00, 0x7FFF00, 0x3FFE00, 0x3C00, 0x7800, 0xF000, 0x1E000, 0x3C000, 0x78000, 0xF8000, 0x1F0000, 0x3E0000, 0x3C0000, 0x7FFF00, 0xFFFF00, 0xFFFF00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
else if(asciiChar == 0x7B) Model = int[](0x0, 0xFE00, 0x1FE00, 0x3C000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x78000, 0x7F0000, 0x7E0000, 0x7F0000, 0x78000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x38000, 0x3C000, 0x1FE00, 0x7E00);
else if(asciiChar == 0x7C) Model = int[](0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000);
else if(asciiChar == 0x7D) Model = int[](0x0, 0x7E0000, 0x7F8000, 0x3C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1E000, 0xFE00, 0x7E00, 0xFE00, 0x1E000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x1C000, 0x3C000, 0x7F8000, 0x7E0000);
else if(asciiChar == 0x7E) Model = int[](0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C0180, 0x7F01C0, 0xFF83C0, 0x1E7E780, 0x1C1FF80, 0x380FF00, 0x1803C00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);

为方便 后续使用,增加一些常量定义

// 各字符的ASCII值
#define CHAR_NOT 				0x21			// !
#define CHAR_QUOTE2 			0x22			// "
#define CHAR_SHARP 				0x23			// #
#define CHAR_DOLLAR 			0x24			// $
#define CHAR_PERCENT 			0x25			// %
#define CHAR_AND 				0x26			// &
#define CHAR_QUOTE1 			0x27			// '
#define CHAR_PARENTHESES_LEFT 	0x28			// (
#define CHAR_PARENTHESES_RIGHT 	0x29			// )
#define CHAR_STAR 				0x2A			// *
#define CHAR_PLUS 				0x2B			// +
#define CHAR_COMMA 				0x2C			// ,
#define CHAR_MINUS 				0x2D			// -
#define CHAR_DOT 				0x2E			// .
#define CHAR_SLASH 				0x2F			// /
#define CHAR_0 					0x30			// 0
#define CHAR_1 					0x31			// 1
#define CHAR_2 					0x32			// 2
#define CHAR_3 					0x33			// 3
#define CHAR_4 					0x34			// 4
#define CHAR_5 					0x35			// 5
#define CHAR_6 					0x36			// 6
#define CHAR_7 					0x37			// 7
#define CHAR_8 					0x38			// 8
#define CHAR_9 					0x39			// 9
#define CHAR_COLON 				0x3A			// :
#define CHAR_SEMICOLON 			0x3B			// ;
#define CHAR_LT 				0x3C			// <
#define CHAR_EQ 				0x3D			// =
#define CHAR_GT 				0x3E			// >
#define CHAR_QUESTION 			0x3F			// ?
#define CHAR_AT 				0x40			// @
#define CHAR_A 					0x41			// A
#define CHAR_B 					0x42			// B
#define CHAR_C 					0x43			// C
#define CHAR_D 					0x44			// D
#define CHAR_E 					0x45			// E
#define CHAR_F 					0x46			// F
#define CHAR_G 					0x47			// G
#define CHAR_H 					0x48			// H
#define CHAR_I 					0x49			// I
#define CHAR_J 					0x4A			// J
#define CHAR_K 					0x4B			// K
#define CHAR_L 					0x4C			// L
#define CHAR_M 					0x4D			// M
#define CHAR_N 					0x4E			// N
#define CHAR_O 					0x4F			// O
#define CHAR_P 					0x50			// P
#define CHAR_Q 					0x51			// Q
#define CHAR_R 					0x52			// R
#define CHAR_S 					0x53			// S
#define CHAR_T 					0x54			// T
#define CHAR_U 					0x55			// U
#define CHAR_V 					0x56			// V
#define CHAR_W 					0x57			// W
#define CHAR_X 					0x58			// X
#define CHAR_Y 					0x59			// Y
#define CHAR_Z 					0x5A			// Z
#define CHAR_BRACKET_LEFT 		0x5B			// [
#define CHAR_SLASH_BACK			0x5C			// \反斜杠
#define CHAR_BRACKET_RIGHT 		0x5D			// ]
#define CHAR_XOR 				0x5E			// ^
#define CHAR_UNDERLINE 			0x5F			// _
#define CHAR_QUOTE_JS 			0x60			// `
#define CHAR_a 					0x61 			// a
#define CHAR_b 					0x62  			// b
#define CHAR_c 					0x63  			// c
#define CHAR_d 					0x64  			// d
#define CHAR_e 					0x65  			// e
#define CHAR_f 					0x66  			// f
#define CHAR_g 					0x67  			// g
#define CHAR_h 					0x68  			// h
#define CHAR_i 					0x69  			// i
#define CHAR_j 					0x6A  			// j
#define CHAR_k 					0x6B  			// k
#define CHAR_l 					0x6C  			// l
#define CHAR_m 					0x6D  			// m
#define CHAR_n 					0x6E  			// n
#define CHAR_o 					0x6F  			// o
#define CHAR_p 					0x70  			// p
#define CHAR_q 					0x71  			// q
#define CHAR_r 					0x72 			// r
#define CHAR_s 					0x73  			// s
#define CHAR_t 					0x74  			// t
#define CHAR_u 					0x75  			// u
#define CHAR_v 					0x76  			// v
#define CHAR_w 					0x77  			// w
#define CHAR_x 					0x78  			// x
#define CHAR_y 					0x79  			// y
#define CHAR_z 					0x7A  			// z
#define CHAR_BRACE_LEFT 		0x7B  			// {
#define CHAR_OR 				0x7C  			// |
#define CHAR_BRACE_RIGHT 		0x7D  			// }
#define CHAR_WAVE 				0x7E  			// ~

现在,就可以画出字符

// 【文本信息】在指定位置(leftTopPoint)输出字符asciiChar,字体大小fontSizeRatio * 32,颜色fontColor
vec4 textLog_Char(vec2 uv, vec2 leftTopPoint, int asciiChar, int fontSizeRatio, vec4 fontColor, out bool inFlag) {
	float characterWidth = float(fontSizeRatio) * 32.0;
	inFlag = isInRange(uv.x, leftTopPoint.x, leftTopPoint.x + characterWidth / pageSize.x) &&
			 isInRange(uv.y, leftTopPoint.y, leftTopPoint.y + characterWidth / pageSize.y);
	if(inFlag) {
		int Model[32];
        if(...) // 字模代码
		else {
			inFlag = false;
			return vec4(0);
		}
		vec2 offset = uv - leftTopPoint;
		int col = int(offset.x * pageSize.x / float(fontSizeRatio) + 0.5);
		int row = int(offset.y * pageSize.y / float(fontSizeRatio) + 0.5);
		if(col > 31) col = 31;
		if(row > 31) row = 31;
		col = 31 - col;
		int value = Model[row];
		if(col > 0)
			value >>= col;
		if((value & 1) > 0) 
			return fontColor;
		else
			inFlag = false;
	}
	return vec4(0, 0, 0, 1);
}

比如,要输出翻页拆线与哪几边相交,就可以用L、T、R、B等字符指示

if(isInRange(solutionTop.x, pageLeft, pageRight)) {
	solutionPoints[pointIndex++] = solutionTop;
	loggedColor = textLog_Char(uv, vec2(0.55, 0.1 * float(pointIndex)), CHAR_T, 1, logFontColor, inFlag);
	if(inFlag) color = loggedColor;
	upDownNumber++;								
}
if(isInRange(solutionBottom.x, pageLeft, pageRight)) {
	solutionPoints[pointIndex++] = solutionBottom;
	loggedColor = textLog_Char(uv, vec2(0.55, 0.1 * float(pointIndex)), CHAR_B, 1, logFontColor, inFlag);
	if(inFlag) color = loggedColor;
	upDownNumber++;
}
if(isInRange(solutionLeft.y, pageTop, pageBottom)) {
	solutionPoints[pointIndex++] = solutionLeft;
	loggedColor = textLog_Char(uv, vec2(0.55, 0.1 * float(pointIndex)), CHAR_L, 1, logFontColor, inFlag);
	if(inFlag) color = loggedColor;
}
if(isInRange(solutionRight.y, pageTop, pageBottom)) {
	solutionPoints[pointIndex++] = solutionRight;
	loggedColor = textLog_Char(uv, vec2(0.55, 0.1 * float(pointIndex)), CHAR_R, 1, logFontColor, inFlag);
	if(inFlag) color = loggedColor;
}

则在翻页过程中,实时指示出计算结果,以查看运算过程与结果是否有误。 

 相应扩展一下,可以直接输出整数、浮点数、向量、矩阵等信息,不再赘述。

 

 

【Godot4自学手册】第四十三用着色器(shader)给纹理描边 这一节我们学一下用着色器(shader)描边效果。片段着色器(Fragment Shader)是一种运行在图形处理单元(GPU)上的程序,用于计算并确定屏幕上每个像素的颜色。片段着色器是图形渲染过程中的关键部分,它们使得开发者能够创造出丰富和动态的视觉效果。 阅读详情

相关推荐

【Godot4自学手册】第二十九节使用Shader来实现敌人受伤的闪白效果

在Godot 4中,Shader是用来为材质提供自定义渲染效果的程序。材质可以应用于MeshInstance、CanvasItem和ParticleEmitter等节点。Shader可以影响顶点的变换、片段(像素)的颜色,以及光照与物体的交互。在Godot中,Shader的编写和使用通常涉及以下步骤:选择或创建一个材质节点。1. 在材质的Shader属性中,选择Custom(自定义)或者Add来创建一个新的Shader。2.切换到Godot的Shader编辑器,这是编写和测试Shader的地方。

zhaoyang314的博客 2611

[Godot] Shader实现几种简单的效果

分享几种Shader效果,草地晃动、波浪效果、波纹效果、雪花屏效果、果冻效果、呼吸膨胀效果、扫描线效果。

qq_58742026的博客 2542

Godot着色器开发指南:从基础到实战,告别千篇一律的游戏视觉效果

着色器是运行在GPU上的小程序,直接控制屏幕上每个像素的最终颜色、亮度等视觉属性,是计算机图形学中实现高级视觉效果的核心技术。其工作原理基于并行计算模型,能够对数百万像素同时执行指令,通过处理纹理、法线、光照等输入数据,输出最终颜色值,从而实现传统渲染管线难以达到的个性化视觉效果。在游戏开发、实时渲染、影视特效等领域,着色器技术是实现风格化艺术表达和性能优化的关键。本文以Godot Engine 4.0为实践平台,通过动态波动、溶解消融、卡通渲染等实战案例,系统讲解着色器开发从思维转变、环境搭建到性能优化的

weixin_30383279的博客 461

浅尝一下Godot Shader

写得有点多了,本来不想说这么多的。本来不像碰shader的,但是还是抵挡不住美术的诱惑,后来才发现以前被Unity坑了,觉得写Shader是种折磨。GodotShader真的很好写。

m0_73087695的博客 4025

Godot着色器编程实战:基于《The Book of Shaders》的完整适配与学习指南

着色器编程是计算机图形学的核心技术之一,它通过在GPU上执行并行计算,实现对每个像素的颜色和属性进行精细化控制。其原理基于图形渲染管线中的片段处理阶段,开发者可以编写GLSL等着色语言代码来定义光照、纹理、颜色混合等视觉效果。这项技术的价值在于能够高效创建从基础材质到复杂视觉特效的各类图形表现,极大地提升了渲染的真实感和艺术表现力。在游戏开发、数据可视化、创意编程等应用场景中,着色器技术都发挥着关键作用。本文聚焦于将经典的《The Book of Shaders》教程体系完整迁移至Godot引擎环境,通过系

weixin_30608503的博客 351

Godot引擎实现《旷野之息》风格卡通渲染着色器教程

卡通渲染(Toon Shading)是一种非真实感渲染技术,它通过简化光影过渡、强化轮廓和色彩分层,模拟出手绘动画的视觉风格。其核心原理在于用阶跃式(Ramp)或分段的色彩映射替代连续的光照计算,并结合基于法线与视角的边缘光(Rim Light)来增强立体感。这种技术在游戏开发中具有重要价值,能显著提升项目的艺术表现力与风格化辨识度,广泛应用于二次元、卡通和低多边形美术风格的项目中。本文聚焦于在开源引擎Godot中,从零实现类似《塞尔达传说:旷野之息》标志性的柔和卡通渲染效果,详细拆解了其阶跃式光影、风格化

weixin_29006701的博客 278

使用RenderDoc深度调试Godot游戏:从图形问题诊断到性能优化

图形调试是游戏开发中诊断渲染错误和进行性能优化的关键技术。其核心原理在于捕获并分析应用程序向GPU发出的绘制指令,从而透视整个渲染管线。这项技术的价值在于能够精准定位视觉瑕疵的根源,例如材质显示异常、深度冲突或着色器错误,同时为性能瓶颈分析提供数据支撑,如分析Draw Call数量、渲染目标切换频率和着色器复杂度。在游戏开发,特别是使用Godot引擎进行3D渲染和特效制作时,图形调试工具的应用场景尤为广泛。本文聚焦于如何利用RenderDoc这一开源图形调试器,针对Godot项目进行帧数据捕获与深度分析,有

weixin_29016315的博客 371

Godot4 2D水波纹Shader实战:从正弦波原理到动态交互实现

在2D游戏开发中,Shader是实现动态视觉效果的核心技术之一,它通过在GPU上并行处理像素,高效地修改纹理渲染方式。其基本原理是通过着色器程序对纹理坐标(UV)进行数学变换,从而改变最终输出的像素颜色。这项技术的核心价值在于能以极低的性能开销实现复杂的动态效果,尤其适合需要大面积、实时交互的场景,如水面、魔法特效和环境氛围渲染。在Godot引擎中,ShaderMaterial作为Shader的载体,为开发者提供了便捷的可视化参数调节和运行时动态控制接口。本文以2D水波纹效果为例,深入解析如何利用正弦波函数

weixin_29001423的博客 324

Godot 4 中基于物理的大气散射天空渲染实现与优化

在实时渲染领域,天空渲染是构建沉浸式虚拟环境的基础。传统贴图天空盒虽然性能高效,但缺乏动态变化和物理准确性。为了突破这一限制,基于物理的大气散射模型成为核心技术。其原理主要模拟光线在大气层中与空气分子和气溶胶粒子发生的瑞利散射和米氏散射过程,通过计算视线路径上散射光的累积积分,来生成具有波长依赖性的天空颜色。这项技术的核心价值在于能够实现与光照动态联动的、符合物理规律的天空效果,例如逼真的蓝天、日出日落色彩以及体积光现象。在工程实践中,这尤其适用于需要动态昼夜循环的开放世界游戏、飞行模拟等应用场景。本文将以

aizexi2652的博客 304

从视觉着色器到代码:Godot4水波纹效果的两种实现方式对比

本文深入对比了在Godot4中实现水波纹效果的两种核心方法:Visual Shader(视觉着色器)与代码着色器(ShaderMaterial)。文章从着色器原理出发,详细解析了两种工作流的构建过程、调试体验、性能表现及适用场景,为开发者根据项目需求、团队技能和效果复杂度选择最佳方案提供了清晰的决策指南。

weixin_29010003的博客 489

Godot4水波纹Shader实战:从零构建动态水面效果与UV扰动原理

在实时图形渲染中,Shader是实现复杂视觉效果的核心技术,它通过编写程序控制GPU对每个像素的处理方式。其基本原理在于操作纹理坐标(UV)、颜色和光照信息,通过数学函数和纹理采样生成最终图像。这项技术的核心价值在于能以极高的效率实现从基础材质到动态特效的各类渲染需求,尤其在游戏开发中,对于提升水面、火焰、云雾等自然现象的视觉真实感至关重要。应用场景广泛覆盖了游戏水面模拟、UI动效以及影视特效预览等领域。本文聚焦于Godot引擎,通过实战解析如何利用ShaderMaterial和UV扰动技术,结合噪声纹理与

weixin_29006701的博客 325

Godot引擎PS1复古风格着色器实战:顶点抖动、像素化与色彩抖动全解析

着色器(Shader)作为现代图形渲染的核心技术,通过编写运行在GPU上的小程序,实现了对顶点、像素等图形数据的精细控制,是创造独特视觉风格的关键。其原理在于替代固定的渲染管线,允许开发者自定义光照、颜色、几何变形等效果,从而在实时渲染中实现从写实到风格化的无限可能。在游戏开发领域,着色器的技术价值尤为突出,它不仅能提升画面表现力,更是塑造游戏美术风格、营造沉浸感的核心工具。特别是在复古风格游戏开发中,通过模拟早期硬件(如PlayStation 1)的渲染特性,可以精准复刻特定的时代美学。本文聚焦于Godo

327

Godot 4 Shader入门:从Uniform变量掌握动态渲染与游戏交互

在计算机图形学中,着色器(Shader)是GPU上运行的小程序,负责处理顶点变换和像素着色,是现代游戏与交互应用实现视觉特效的核心技术。其工作原理是通过渲染管线将几何数据转化为屏幕像素,其中Uniform变量作为关键机制,允许CPU向GPU传递全局常量数据,实现着色器参数的动态控制。这一技术价值在于打破了静态渲染的限制,使视觉效果能够实时响应游戏逻辑,极大提升了渲染系统的灵活性与表现力。在游戏开发、UI动效、数据可视化等应用场景中,Uniform变量常用于控制颜色、强度、时间等参数,是实现动态材质、交互特效

weixin_33859231的博客 376

Godot引擎2D游戏开发:从零构建疾病状态系统的技术实践

2D游戏开发是现代游戏制作的重要分支,其核心原理基于场景图管理和物理引擎交互。在技术价值层面,2D开发相比3D具有更低的硬件要求和更快的迭代速度,特别适合独立开发者和中小团队。Godot引擎作为开源游戏引擎,在2D领域表现出色,其节点系统为状态管理提供了天然支持。状态机是游戏开发中的基础概念,通过状态转换可以实现复杂的游戏逻辑,如角色健康系统、疾病感染机制等典型应用场景。本文以疾病状态系统为例,结合着色器视觉反馈和碰撞检测,展示了如何在Godot中实现完整的2D游戏框架,为类似《DISEASE》的项目提供可

weixin_34354173的博客 308

UniTouch:多模态触觉对齐技术如何重塑零样本跨模态应用

UniTouch模型通过创新的多模态触觉对齐技术,成功将触觉数据映射到通用的视觉-语言嵌入空间,解决了触觉模态的“孤岛困境”。该技术利用对比学习和传感器特定标记,实现了高质量的零样本学习能力,使模型无需额外训练即可完成触觉分类、描述等任务,并能驱动跨模态生成,为机器人、VR和智能制造等领域提供了强大的触觉理解新范式。

weixin_29044713的博客 409

保姆级教程:在通达信V7.611上配置欧奈尔RPS曲线(附完整公式与每日更新流程)

本文提供通达信V7.611配置欧奈尔RPS曲线的保姆级教程,涵盖从环境准备、基础设置到核心公式配置的全流程。详细讲解如何创建股票池、编写EXTRS基础公式及RPS显示公式,并附每日更新流程与实战应用技巧,帮助投资者精准捕捉强势股。

weixin_30000735的博客 461

Godot Shader内置变量原理与实战避坑指南

Shader内置变量不是静态API,而是渲染管线在特定上下文(如canvas_item或spatial)中动态注入的数据接口。其类型、可用性与数值含义严格依赖渲染阶段、坐标系层级、后端差异(Vulkan/OpenGL)及启用选项(如use_lighting)。理解TIME与DELTA的时间语义差异可避免帧率相关运动异常;辨析UV、SCREEN_UV和FRAGCOORD的坐标系本质(节点归一化/屏幕归一化/像素整数)是解决2D特效错位、UI缩放失准、后处理采样扭曲的关键。这些变量构成Godot着色器工程实践的

weixin_31179927的博客 235

糖尿病预测(深度学习pytorch实现-最新)

本次做的项目是糖尿病的预测,也是来自kaggle上面的一个小项目。根据一个人的怀孕次数、血糖、血压、皮肤厚度、胰岛素指标、身体质量指数、糖尿病谱系指数、年龄等身体参数来预测一个人是否患有糖尿病。

NangoGreen的博客 5358

Godot水体着色器调试指南:常见问题与解决方案大全

在游戏开发中,实现逼真的水体效果是提升视觉体验的关键环节。Godot引擎的Realistic Water Shader项目为开发者提供了强大的水体渲染解决方案,但在实际应用中可能会遇到各种渲染问题。本文将系统梳理水体着色器调试的常见问题与实用解决方案,帮助开发者快速定位并解决问题,打造出令人惊艳的水面效果。 ## 一、准备工作:环境配置与资源检查 在开始调试前,确保你的开发环境和资源配置正确无

gitblog_01196的博客 947

从零到一:在Ubuntu 20.04上搭建ROS1与PX4无人机开发环境

本文详细指导如何在Ubuntu 20.04系统上搭建完整的ROS1与PX4无人机开发环境。内容涵盖ROS Noetic安装、PX4固件源码编译、MAVROS通信桥接以及QGroundControl地面站的配置,并通过Gazebo仿真完成全链路联调测试,为无人机算法开发与验证提供稳定可靠的基础平台。

weixin_29292431的博客 167

【YOLOv8/v9/v10 实战 01】YOLOv8/v9/v10全系列实战对决:性能矩阵、架构拆解与2026部署指南

2026年YOLO生态已进入“战国时代”,Ultralytics YOLOv8/11/26、阿里YOLO12、清华YOLOv10、微软YOLOv9四大路线并行发展。本文基于官方文档、学术论文及实测数据,系统剖析三大核心版本(YOLOv8/v9/v10)的架构演进逻辑,构建覆盖参数量、mAP、FPS、FLOPs的完整性能矩阵。通过8组工业场景实测、全流程代码实现(训练-导出-部署)、6类硬件适配方案,解决新手选型难、进阶者优化无门、工业开发者部署低效的痛点。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 533

Godot Engine着色器实战:从零做出3个游戏视觉特效

游戏画面"千篇一律"的毛病,多半不是模型和美术不够,而是没碰过着色器——一段跑在GPU上的小程序,逐像素算出颜色。用Godot Engine内置的着色语言,你不需要写C++,30分钟左右就能让精灵图呼吸发光、3D模型带上全息扫描线、角色被逐帧溶解,全部效果复制代码即可跑通。 [![Godot Engine启动画面:着色器开发的视觉基础](https://raw.gitcode.com/GitHu

gitblog_01106的博客 881

一文读懂 STAR-CCM+:多物理场仿真王者,从入门到精通全攻略(附实战路线)

STAR-CCM+是西门子旗下的多物理场仿真平台,集流体、传热、结构、电磁等耦合求解于一体。其核心优势包括:全自动网格处理技术(支持十亿级网格)、多物理场无缝耦合、CPU/GPU并行加速计算、流程自动化与设计探索等。广泛应用于汽车(空气动力学优化、电池热管理)、航空航天(气动设计、发动机仿真)、能源(风电叶片流固耦合)、电子(芯片散热)等行业。相比ANSYS Fluent和OpenFOAM,STAR-CCM+在多物理场耦合和复杂几何处理方面更具优势,适合工业级高精度仿真需求。学习路径建议从基础操作入手,逐步

源代码杀手的博客 339

Godot Engine:用Shader实现旗帜飘飘的效果

本文是《【手把手带你Godot游戏开发 第二弹】名场面临摹》的一部分。老王将手把手教大家如何使用Godot引擎的Shader,实现一个游戏中常见的旗帜飘飘的效果。

开发游戏的老王 3721

如何解决Elsevier和IEEE期刊之间参考文献的转换问题

Elsevier期刊和IEEE旗下的期刊两者模版互相转换的时候,会发现Elsevier模版的参考文献是存放在.bib文件下的,然后在.tex文件中直接引用即可。3. 在IEEE的.tex文件中的\end{document}命令行之前,添加下面的这句话(ps:\bibliography{**}中的**名称即为.bib文件的名称)如何将Elsevier的参考文献快速的转成IEEE期刊可用的格式,是本博客需要解决的问题。2. 将下载好的.bib文件,上传到IEEE的latex文件中。

薰珞婷紫小亭子的博客 1675

LLC谐振变换器软启动,不只是“慢启动”,还是“智能启动”

LLC谐振变换器的软启动,不只是“慢慢来”,而是要在控制时序、限流、响应速度之间精妙权衡。而数字控制,特别是用查表法或混合信号法,为实现真正的“最佳轨迹”提供了可能。✨小Tips:如果你的系统成本敏感,选择查表法准没错;如果你的设计目标是超高速响应,那就上混合信号的高配方案!

weixin_43199439的博客 691
上一篇: Godot 4 源码分析 - 获取属性信息
下一篇: Godot 4 源码分析 - 获取脚本
DrGraph
博客等级 码龄14年 228粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值