
汇编程序是我最喜欢的语言...但是寿命很短。
我将继续研究一些百吉饼的合适阴影问题。 发布后,
我为此主题进行了
一次又一次的冷却,但是动作不完全的效果促使我返回到像素碎片,并完成了
格式像 。
认识我自己,我敢肯定这款游戏几乎不会得到体现,但是也许某些公众会对我在这条棘手的道路上所取得的成就感兴趣。 因此,让我们开始吧。
在上一个周期的末尾,我开始了解到,在CPU上计算图形已经是上个世纪了,但是自然的坚持要求:并非所有可能性都被使用了,还有一些有趣的解决方案可供选择。
光线追踪仍未实现。 更准确地说,是一种类型,即对于图像的每个像素(像素块)都发出光线并确定当前点的照明级别。 该算法本身已在上一篇文章中进行了描述,没有必要返回。 对于反向光线跟踪,代码甚至更加简化,所有三角函数都被完全删除,这在将来可能会提供可接受的结果。
las,结果比预期的要差得多,值得将图片部署到全屏状态,FPS希望将其部署到单位。

将像素分组为宏块以减少计算并应用后续的平滑处理并不能改善性能。 坦率地说,这种效果根本不喜欢这个词。

该算法是完全并行的,但是使用大量流没有意义,即使图像质量更好,效果似乎也比上一篇文章差很多。
事实证明这是一个死胡同。 我不得不承认,CPU在计算图形时在我眼中已经筋疲力尽。 窗帘。
题外话1在过去的十年中,通用处理器的开发几乎没有进展。 如果用户接近,则每个内核的最大可观性能提升不超过30%。 温和地说,进步微不足道。 如果我们省略了矢量指令长度的延长,以及传送带块的某些加速,则这是工作核心数量的增加。 使用线程进行安全的工作仍然是一种享受,并不是所有任务都能成功并行化。 我希望有一个工作核心,尽管只有一个,但如果有的话,它的速度要快5到10,但可惜的是,正如他们所说。
在哈布雷(Habré)上,有一系列精彩的文章
“黑暗的“硅时代”中的生活,它解释了当前局势的一些先决条件,但也从天而降。 在接下来的十年中,您不能指望每个内核的计算量会大幅增加。 但是我们可以期待GPU内核数量及其整体加速的进一步发展。 即使在我的旧笔记本电脑上,估计的总GPU性能也比单个CPU线程高20倍。 即使您有效地加载了所有4个处理器内核,也比我们想要的要少得多。
我向过去的图形开发人员表示敬意,他们在没有硬件加速器的情况下制作了杰作,是真正的大师。
因此,我们处理GPU。 事实证明,在实际实践中,很少有人会简单地将多边形散布成形状。 所有有趣的事物都是使用
着色器创建的。 抛弃了完成的3D引擎之后,我试图深入研究技术的杂念。 相同的处理器和相同的汇编器,只有一些截短的指令集和它们自己的工作细节。 为了进行测试,我在
GLSL停了下来,
GLSL是一种类似于C的语法,非常简单,提供了许多培训课程和示例,包括Habr。
由于我通常习惯于使用
Pascal进行编写,因此任务是如何连接OpenGL。
到项目。 我设法找到两种连接方式:
GLFW库和
dglOpenGL头文件。 首先,我唯一无法连接着色器,但是显然这是由于手的弯曲造成的。
离题2许多朋友问我为什么用Pascal写作? 显然,这是一种濒临灭绝的语言,它的社区正在稳步下降,几乎没有发展。 低级系统工程师更喜欢C,以及Java,Python,Ruby或目前处于顶峰的任何版本。
对我来说,帕斯卡(Pascal)类似于初恋。 二十年前,在
Turbo Pascal 5.5时代 ,它沉入我的灵魂,并一直与我同行,无论是Delphi还是最近几年的
Lazarus 。 我喜欢这种语言的可预测性,相对较低的级别(汇编器插入并查看处理器指令),与C的兼容性。主要是代码的汇编和执行没有问题,但它并不流行,过时且有一些功能,这是胡说八道。 有传言说,有些人仍然在写
LISP ,但是对他来说一般来说已经有半个世纪了。
因此,让我们深入研究开发。 对于测试步骤,我们不会采用精确的逼真的阴影模型,而是尝试实现我们之前尝试过的但具有GPU性能的模型,因此可以进行清晰的比较。
最初,我想到使用三角形作为对象来获得近似此形状的阴影。

要创建圆滑的效果,需要大量的多边形。 但是,如果您最少使用三角形,使用像素着色器在形状中创建孔,该怎么办。 在读了
一位受人尊敬的大师的
文章后,我想到了这个主意,在
这篇文章中,有机会创造了一个使用着色器的球体。

如果将三角形扩展到屏幕边界之外,则结果如下:

阴影的边界变得非常僵硬并且也呈阶梯状。 但是有一种方法可以在不使用
超采样的情况下获得可接受的结果,这是使用平滑的边框。 为此,请稍微更改方案。 与圆切线相交的多边形的角将变为透明。

结果更好,但看起来仍然不自然。

在圆上添加一点平滑以使其柔和,并将渐变的形式从线性更改为幂。

这是可以接受的结果。
最后,我们将向表单添加模仿障碍物的对象。

着色器代码//
#version 330 core
layout (location = 0) in vec2 aVertexPosition;
void main(void) {
gl_Position = vec4(aVertexPosition.xy, 0, 1.0);
}
//
#version 330 core
layout (points) in;
layout (triangle_strip, max_vertices = 5) out;
uniform mat4 uModelViewMatrix;
uniform float uRadius;
uniform vec2 uHeroPoint;
out float fTransparency;
out vec2 vCenter;
void main(){
vCenter = gl_in[0].gl_Position.xy;
vec2 d = uHeroPoint - vCenter;
float l = length(d);
float i = uRadius / l;
float ii = i*i;
float ij = i * sqrt(1 - ii);
vec2 p1 = vec2(vCenter.x + dx*ii - dy*ij , vCenter.y + dx*ij + dy*ii);
vec2 p2 = vec2(vCenter.x + dx*ii + dy*ij , vCenter.y - dx*ij + dy*ii);
d = uHeroPoint - p1;
vec2 p3 = vec2(p1 - d/length(d)*1000000);
d = uHeroPoint - p2;
vec2 p4 = vec2(p2 - d/length(d)*1000000);
fTransparency = 0;
gl_Position = uModelViewMatrix * vec4(p1, 0, 1);
EmitVertex();
fTransparency = 1;
gl_Position = uModelViewMatrix * vec4(p3, 0, 1);
EmitVertex();
gl_Position = uModelViewMatrix * vec4(vCenter, 0, 1);
EmitVertex();
gl_Position = uModelViewMatrix * vec4(p4, 0, 1);
EmitVertex();
fTransparency = 0;
gl_Position = uModelViewMatrix * vec4(p2, 0, 1);
EmitVertex();
EndPrimitive();
}
//
#version 330 core
precision mediump float;
varying float fTransparency;
varying vec2 vCenter;
uniform float uRadius;
uniform vec2 uScreenHalfSize;
uniform float uShadowTransparency;
uniform float uShadowSmoothness;
out vec4 FragColor;
void main(){
float l = distance(vec2((gl_FragCoord.xy - uScreenHalfSize.xy)/uScreenHalfSize.y), vCenter.xy);
if (l<uRadius) {discard;}
else {FragColor = vec4(0, 0, 0, min(pow(fTransparency, uShadowSmoothness), (l-uRadius)/uRadius*10)*uShadowTransparency);}
}
我希望它能提供信息
您卑微的仆人,像素折磨者,重建者。
我附上一个小
样片 。 (EXE Windows)
PS文章的标题包含一个
复活节彩蛋 ,是对《
Siala Chronicle》三部曲的引用。 阿列克谢·佩霍夫(Alexei Pekhov)的一部奇幻风格的出色作品,讲述了牛角的不幸。