GPU处理图像 Shader的入门

2023-11-07

from:http://www.jianshu.com/p/8687a040eb48
字数2901  阅读316  评论0  喜欢3

Shader着色器

Shader出现在OpenGL ES 2.0中,允许创建自己的Shader。必须同时创建两个Shader,分别是Vertex shader和Fragment shader.

Shader工具

Shader会有很多坑,不过一些工具能够帮助你跳过这些坑

Shader使用范例

Vertex shader

attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;
void main()
{
     gl_position = position;
     textureCoordinate = inputTextureCoordinate.xy;
}

Fragment shader

直通滤镜

varying highp vec2 textureCoordinate; //highp属性负责变量精度,这个被加入可以提高效率
uniform sampler2D inputImageTexture; //接收一个图片的引用,当做2D的纹理,这个数据类型就是smpler2D。
void main()
{
     gl_FragColor = texture2D(inputImageTexture, textureCoordinate); //texture是GLSL(着色语言)特有的方法
}

GLSL着色语言

GLSL的官方快速入门指导

变量赋值

三个可以赋值给我们的变量的标签

  • Uniforms:在渲染循环里作为不变的输入值
  • Attributes:随顶点位置不同会变的输入值
  • Varyings:用来在Vertex shader和Fragment shader之间传递信息的,比如在Vertex shader中写入varying值,然后就可以在Fragment shader中读取和处理

向量

有很多种向量,但是有三种会经常看到

  • vec2:两个浮点数,适合在Fragment shader中保存X和Y坐标的情况
  • vec3:三个浮点数
  • vec4:四个浮点数,在图像处理中持续追踪每个像素的R,G,V,A这四个值。

矩阵

是浮点数组的数组。三个经常处理的矩阵对象

  • mat2:相当于保存了两个vec2对象的值或四个浮点数。
  • mat3
  • mat4

向量和矩阵运算

线性代数发挥作用的地方。想知道线性代数如何工作可以看这个资源站:http://betterexplained.com/articles/linear-algebra-guide/

线性代数可以一次在很多值上进行并行操作,so,正好适合需求,GLSL内建了很多函数可以处理庞大的计算转换

GLSL特有函数

GLSL内建的函数可以在Shaderific网站上找到:http://www.shaderific.com/glsl-functions。很多C语言数学库基本数学运算都有对应的函数。

  • step():GPU处理条件逻辑不是很好。step()允许在不产生分支的前提下实现条件逻辑。传入step()函数的值小于阈值就返回0.0,大于等于阈值就返回1.0。
  • mix():将两个颜色值混合为一个。
  • clamp():可以确保值在一个区间内。

复杂的Shader的例子

一个饱和度调节的Fragment shader的例子,出自《图形着色器:理论和实践》这本书。

varying highp vec2 textureCoordinate; //

uniform sampler2D inputImageTexture;
uniform lowp float saturation;

const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); //光亮度里三个值相加要为1,各个值代表着颜色的百分比,中间是绿色的值,70%的比重会让效果更好点。

void main()
{
     lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); //根据坐标取样图片颜色信息
     lowp float luminance = dot(textureColor.rgb, luminanceWeighting); //GLSL中的点乘运算,线性代数的点运算符相乘两个数字。点乘计算需要将纹理颜色信息和相对应的亮度权重相乘。然后取出所有的三个值相加到一起计算得到这个像素的中和亮度值。
     lowp vec3 greyScaleColor = vec3(luminance); //创建一个三个值都是亮度信息的vec3,如果只指定一个值,编译器会将其它的都设置成这个值
     gl_FragColor = vec4(mix(greyScaleColor, textureColor.rgb, saturation), textureColor.w); //用mix函数把计算的灰度值,初识的纹理颜色和得到的饱和度信息结合起来。
}

球形滤镜示例

varying highp vec2 textureCoordinate;

uniform sampler2D inputImageTexture;

uniform highp vec2 center;
uniform highp float radius;
uniform highp float aspectRatio;
uniform highp float refractiveIndex;

void main()
{
     highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); //归一化坐标空间需要考虑屏幕是一个单位宽和一个单位长。
     highp float distanceFromCenter = distance(center, textureCoordinateToUse); //计算特定像素点距离球形的中心有多远。使用GLSL内建的distance()函数,用勾股定律计算出中心坐标和长宽比矫正过的纹理坐标的距离
     lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius); //计算片段是否在球体内。

     distanceFromCenter = distanceFromCenter / radius;  //标准化到球心的距离,重新设置distanceFromCenter

     highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter); //模拟一个玻璃球,需要计算球的“深度”是多少。
     highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth)); //归一化

     highp vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex); //GLSL的refract()函数以刚才创建的球法线和折射率来计算当光线通过球时从任意一个点看起来如何。

     gl_FragColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere; //最后凑齐所有计算需要的颜色信息。
}

调试Shader

使用gl_FragColor调试代码。GPUImage是个开源的资源有些很酷的shader,非常好的学习shader的方式,可以拿一个你觉得很有意思的shader对着源码一点点看下去。GPUImage还有一个shader设计器https://github.com/BradLarson/GPUImage/tree/master/examples/Mac/ShaderDesigner 的Mac应用,可以测试shader而不用准备OpenGL代码。

性能调优

简单的方法达到调优目的,可以用下载Imagination Technologies PowerVR SDKhttp://community.imgtec.com/developers/powervr/这个工具帮助分析shader

  • 消除条件逻辑:使用step()这样的函数
  • 减少依赖纹理的读取:如果希望从附近像素取样而不是计算Fragment shader相邻像素的偏差,最好在Vertex shader中计算然后把结果以varying的方式传入Fragment shader里。
  • 计算尽量简单:能够得到一个近似值就尽量用,不要用类似sin(),cos(),tan()的比较消耗的操作。
  • 尽可能的将计算放到Vertex上:如果计算在图片上会有相同的结果或线性变化最好这样做。因为Vertex shader对每个顶点运行一次,而Fragment shader会在每个像素上运行一次。
  • 移动设备使用合适的精度:在向量上使用低精度的值会变得更快。两个lowp vec4相加可以在一个时钟周期内完成,两个highp vec4相加则需要四个时钟周期。

边界探测

基于OpenCV库,不过这些步骤在GPUImage中都有完整的实现

Sobel边界探测

这种操作在滤镜方面比机器视觉方面多。Sobel边界探测用于探测边界的出现位置,边界是由明变暗或者由暗变明的区域。在被处理的图片中一个像素的亮度反映了这个像素周围边界的强度。

  • 第一步,将彩色图片弄成灰阶图,这个过程就是将每个像素的红绿蓝部分合一代表亮度的值。如是果YUV而不是RGB格式的可以省略这步,因为YUV是将亮度信息和色度信息分开的。如果简化到只剩亮度的话一个像素周围的边界强度就可以由周围3*3个临近像素计算得到。这个计算涉及Convolution Matrix(卷积矩阵),每个像素都要与这个矩阵计算出一个数值,因为没有顺序要求所以可以采取并行运算。
  • Sobel的水平处理矩阵

-1 0 +1
-2 0 +2
-1 0 +1

  • Sobel的垂直矩阵

-1 -2 -1
0 0 0
+1 +2 +1

  • 和Sobel类似的变体,Prewitt边界探测。这个变体会在横向竖向矩阵中用不同的矩阵,但是运作过程差不多。
  • OpenGL ES代码
precision mediump float;

//varying的都是在Vertex shader上定义了
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;

varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;

varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;

uniform sampler2D inputImageTexture;

void main()
{
     float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
     float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
     float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
     float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
     float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
     float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
     float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
     float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;

     float h = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
     float v = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
     float mag = length(vec2(h, v)); //length()函数计算出水平和垂直矩阵转化后值的平方和的平方根的值,这个值会被拷贝进输出像素的红绿蓝通道中,这样就可以来代表边界的明显程度了。

     gl_FragColor = vec4(vec3(mag), 1.0);
}

Canny边界探测

Canny探测会比Sobel复杂些,这样做会得到一条物体边界的干净线条。

探测过程:

  • 先用Sobel矩阵得到边界梯度的强度。这个和Sobel比就是最后一个计算有些不同
vec2 gradientDirection;
gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;

float gradientMagnitude = length(gradientDirection);
vec2 normalizedDirection = normalize(gradientDirection);
normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away
normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0

gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0);
  • 着色器步骤
precision mediump float;

varying highp vec2 textureCoordinate;

uniform sampler2D inputImageTexture;
uniform highp float texelWidth; //要处理的图片中临近像素之间的距离。
uniform highp float texelHeight; //同上
uniform mediump float upperThreshold; //预期边界强度上下限
uniform mediump float lowerThreshold; 

void main()
{
     vec3 currentGradientAndDirection = texture2D(inputImageTexture, textureCoordinate).rgb;
     vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(texelWidth, texelHeight);

     float firstSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate + gradientDirection).r;
     float secondSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate - gradientDirection).r;

     float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r);
     multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r);

     float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r);
     multiplier = multiplier * thresholdCompliance;

     gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0);
}

Harris边角探测

多步骤的方法来探测场景中的边角。

  • 先弄得只有亮度信息,再通过Sobel矩阵,普里维特矩阵或者其它相关的矩阵计算出一个像素X和Y方向的梯度值,计算的结果会将X梯度传入红色部分,Y梯度传入绿色部分,X与Y梯度的乘积传入蓝色部分。
  • 对计算的结果进行高斯模糊。将模糊后图中取出红绿蓝编码的值带到计算边角点可能性公式:

R = Ix2 × Iy2 − Ixy × Ixy − k × (Ix2 + Iy2)2

资料

相关数学

相关GLSL

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GPU处理图像 Shader的入门 的相关文章

  • 如何将点光源转换为卵形/椭圆形?

    我希望通过具有不同 x 和 y 值的 vec2 半径将当前的圆形光变成椭圆形 有没有办法根据我当前在片段着色器中的代码来做到这一点 uniform struct Light vec4 colour vec3 position vec2 ra
  • 简单的线框格式?

    我正在寻找一种用于线框模型的简单文件格式 我知道 VRML u3D 等 但这些对于我的需求来说似乎很重要 我的标准是 必须有明确的规格 要么是开放的 要么是非常完善 记录的 我只需要 想要 简单的模型 顶点和边 我不想处理面孔或物体 如果格
  • OpenGL 中连续暂停

    void keyPress unsigned char key int x int y int i switch key case f i 3 while i x pos 3 sleep 100 glutPostRedisplay 上面是在
  • glBlitFramebuffer 渲染缓冲区和渲染全屏纹理哪个更快?

    哪个更快更高效 使用 OpenGL 纹理作为 CUDA 表面并在四边形上渲染 新样式 使用渲染缓冲区作为 CUDA 表面并使用 glBlitFramebuffer 进行渲染 None
  • NV_path_rendering替代方案[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我刚刚观看了 Siggraph 2012 的一个非常令人印象深刻的演示 http nvidia fullviewmedia com sig
  • 使用 C# 截取任何外部应用程序的屏幕截图

    我们有一个 C WPF 应用程序 我们想要在其中截取我们启动的任意应用程序的屏幕截图 即 我们可以引用我们启动的进程 应用程序可能已最小化或位于其他窗口后面 但我们仍然只需要单个应用程序的图像 而不是重叠像素 我知道使用 BitBlt 或的
  • 如果我用opengl绘图的话SDL Renderer就没用了吗?

    我正在学习 SDL2 但我也在使用使用 OpenGL 调用的 imgui 库 从我在网上各种博客上读到的内容来看 我无法轻松混合 SDL2 渲染器和 opengl 调用 我要么使用其中之一 要么使用另一个 我读过的大多数教程都使用渲染器 所
  • PyQt5 的 OpenGL 模块和版本控制问题(调用不正确的 _QOpenGLFunctions_(ver))

    我一直在努力得到PyQt5 helloGL 示例代码 https github com baoboa pyqt5 blob master examples opengl hellogl py编译 当我尝试构建解决方案时 我得到 Traceb
  • Opengl 像素完美 2D 绘图

    我正在研究 2d 引擎 它已经工作得很好 但我不断收到像素错误 例如 我的窗口是 960x540 像素 我从 0 0 到 959 0 画一条线 我希望扫描线 0 上的每个像素都会被设置为一种颜色 但事实并非如此 最右边的像素没有被绘制 当我
  • 三角形纹理映射OpenGL

    我正在开发一个使用 Marching Cubes 算法并将数据更改为 3D 模型的项目 现在我想在 OpenGL 中为我的 3D 模型使用纹理映射 我首先尝试了一个简单的示例 它将图片映射到三角形上 这是我的代码 int DrawGLSce
  • 使用 JOGL 和 Android OpenGL 编写可移植 Java 应用程序

    我计划编写一款可以在 PC 和 Android 上运行的 Java 3D 游戏 不幸的是 这两个平台似乎没有通用的 OpenGL API API 是否有显着差异 有没有办法在两个版本中使用相同的 3D 代码 这是不是一个好主意 Androi
  • 使用 GLSL 直接在着色器中从位置计算平移矩阵

    我正在开发 C OpengL 程序以及 GLSL 顶点和片段着色器 我正在创建同一对象的多个实例 我只需要改变实例之间的对象位置 这是我所做的 我正在使用一个统一变量 它是一个变换矩阵数组 每个矩阵代表一个对象实例 MVP 也是一个变换矩阵
  • gldrawarrays 不绘制任何东西

    我正在尝试用 VBO 绘制一个三角形 我在窗口上没有看到任何像素 我也没有看到任何 GL ERROR 这是我尝试运行的代码 include
  • 如何使用边缘和内部镶嵌因子完成三角形面片镶嵌?

    I am just learning tessellation and i came across with below example for triangle patch tessellation but i am not sure h
  • SSBO 是更大的 UBO?

    我目前正在 OpenGL 4 3 中使用 UBO 进行渲染 以将所有常量数据存储在 GPU 上 诸如材料描述 矩阵等内容 它可以工作 但是 UBO 的小尺寸 我的实现为 64kB 迫使我多次切换缓冲区 减慢渲染速度 我正在寻找类似的方法来存
  • 用于新 Windows 游戏项目的 OpenGL 或 Direct3D?或者是其他东西?

    我正在 Windows 上启动一个爱好游戏项目 该项目将大量使用 3D 图形效果 它很可能是用 C 编写的 我应该使用 OpenGL 还是 Direct3D 作为我的图形后端 为什么 或者我应该使用现成的图形引擎 例如OGRE 3D htt
  • 在windows + opengl中选择图形设备

    我知道如何使用 openGL 打开窗口 使用 Win32 或其他工具包 但是当系统有2块显卡时 如何选择要渲染的图形设备 我的编程语言是 C 我专注于 Windows 但任何示例都将受到欢迎 编辑 也许更好地解释我的问题是个好主意 以便添加
  • LibGDX纹理混合与OpenGL混合功能

    在 libGdx 中 我试图创建一个成形纹理 采用完全可见的矩形纹理并将其遮罩以获得成形纹理 如下所示 在这里我在矩形上测试它 但我想在任何形状上使用它 我调查过本教程 http www learnopengles com tag addi
  • 使用 glGetFloatv 检索 pyglet 中的模型视图矩阵

    我正在使用 pyglet 在 python 中进行 3D 可视化 并且需要检索模型视图和投影矩阵来进行一些选择 我使用以下方式定义我的窗口 from pyglet gl import from pyglet window import wi
  • Windows下使用GLEW使用OpenGL扩展

    我一直在 Windows 上使用 OpenGL 扩展痛苦的方式 https stackoverflow com questions 14413 using opengl extensions on windows GLEW 是更简单的方法吗

随机推荐

  • 批量保存数据

    批量保存 批量保存 参数为对象集合 br 条件 对象属性与数据库字段完全对应 允许使用大骆驼拼写法 br 2018年4月28日下午5 30 53 throws Exception private String insert00000 Lis
  • BandZIP无广告版(v6.25)安装及禁止联网设置

    安装和设置 1 下载和安装 bandzip版本v6 25以前的都是免费且无广告的 我们从网上找到6 25版本的进行下载安装 双击 如下图进行设置 点击同意并安装 安装过程中取消自动更新 其他设置默认 安装完成后 虽然不会自动更新 但每次使用
  • C# EasyModbus xktComm Modbus 例子

    转载请注明出处 联系我 田工 15118249062 微信同号 当然先要在NuGet按照相应的dll 不是ModbusRTU报文 在RTU报文前面加了4个字节 transactionIdentifier protocolIdentifier
  • 什么是Scrum?Scrum的核心要点和精髓

    有点长 期望你能通过本文彻底了解 Scrum 我们介绍了一个非常有意思且高效的组织模式 特性团队 我们首先介绍了为什么需要特性团队 特性团队的定义 核心价值 优势 可能存在的问题以及带来的成本 接着讲述了特性团队的适用范围 开发新产品 拓展
  • alertdialog 自定义样式回调选手_把 Node.js 中的回调转换为 Promise

    每日前端夜话 第431篇 正文共 2300 字 预计阅读时间 7 分钟 介绍 在几年前 回调是 JavaScript 中实现执行异步代码的唯一方法 回调本身几乎没有什么问题 最值得注意的是 回调地狱 在 ES6 中引入了 Promise 作
  • C++中的单例模式

    单例模式也称为单件模式 单子模式 可能是使用最广泛的设计模式 其意图是保证一个类仅有一个实例 并提供一个访问它的全局访问点 该实例被所有程序模块共享 有很多地方需要这样的功能模块 如系统的日志输出 GUI应用必须是单鼠标 MODEM的联接需
  • socket选项 SO_REUSEPORT

    摘要 多核与网络IO 目录 前言 本篇用于记录学习SO REUSEPORT的笔记和心得 末尾还会提供一个bindp小工具也能为已有的程序享受这个新的特性 当前Linux网络应用程序问题 运行在Linux系统上网络应用程序 为了利用多核的优势
  • Python毕设-【基于Flask的人脸考勤系统】附源码课件_Python练手项目_JPython毕业设计

    Python毕设 基于Flask的人脸考勤系统 release 附源码课件 允许白嫖 文章目录 系统简介 一 技术框架 二 功能 三 开发工具 四 总结 五 视频演示 文末附获取方式 系统简介 基于Flask的人脸考勤系统是一种应用于公司和
  • 可视化散点图:基于R语言的碎石图

    可视化散点图 基于R语言的碎石图 在数据分析和可视化中 散点图是一种常用的工具 用于展示两个变量之间的关系 而碎石图是散点图的一种变体 能够更直观地显示数据的密度和分布情况 本文将介绍如何使用R语言创建碎石图 并通过代码演示实现过程 首先
  • 如何理解 Istio Ingress, 它与 API Gateway 有什么区别?东西流量?南北流量?

    文章目录 背景 k8s的内部服务如何被外部访问 东西流量 南北流量 流量管理的比较 Ingress API Gateway Istio 参考 背景 这三者都和流量治理密切相关 那么流量治理在过去和现在有什么区别呢 都是如何做的呢 在学习is
  • 【缓存算法】LRU 最近最少使用

    LRU是Least Recently Used 最近最少使用 LRU缓存就是使用这种原理实现 简单的说就是缓存一定量的数据 当超过设定的阈值时就把一些过期的数据删除掉 LRU思想 固定缓存大小 需要给缓存分配一个固定的大小 每次读取缓存都会
  • 记mount NFS遇到的一个问题(-o nolock)

    前两天 测试 过程中 测试机始终 mount 不上我们的 nfs 比如我使用命令 mount vt nfs share mnt share 开始是mount命令一直hang在那里 卡住了 另一种情况是 有类似如下的错误输出 portmap
  • C++ 实现自动产生LR1分析器的产生器

    C 实现自动产生LR1分析器的产生器 1 介绍 2 总体思路 2 1 拓广文法 2 2 计算First集合 2 3 计算每个闭包的项目集以及GO函数 2 4 计算分析表的动作函数ACTION和状态转换函数GOTO 2 5 对语句进行语法分析
  • MySQL数据库学习——DQL——条件查询

    create table emp id int comment 编号 workno varchar 10 comment 工号 name varchar 10 comment 姓名 gender char 1 comment 性别 age
  • QT Critical error detected c0000374

    在使用QT写GraphicsView时 运行程序添加Item时 无缘无故报错了 debug调试也是跳到QT源码上面去 还都不是报同一个位置的错误 有些还是new的位置报错 而报错信息是 Critical error detected c00
  • 多线程案例(单例模式、阻塞式队列、定时器及线程池)

    目录 一 单例模式 1 1 饿汉模式 1 2 懒汉模式 二 阻塞式队列 2 1 生产者消费者模型 2 2 标准库中的阻塞队列 2 3 阻塞队列实现 三 定时器 3 1 标准库中的定时器 3 2 实现定时器 四 线程池 4 1 标准库中的线程
  • office word 页码从任意页开始

    有时候在编写word文档的时候 页码会从封面就开始计算 想象一下如果你的论文封面突然蹦出一个页码 很难受有木有 解决这个问题很简单 网上教程很多 这里总结一下 1 找到你需要从零开始的页面 将这一页和上一页添加分节符 添加分节符1 添加分节
  • 游戏智能作业

    作业题目 P D 过河游戏智能帮助实现 程序具体要求 实现状态图的自动生成 讲解图数据在程序中的表示方法 利用算法实现下一步的计算 参考 P D 过河游戏智能帮助实现 我们先来分析一下这一次作业的要求 这一次的作业大致就是要对之前的牧师与魔
  • DVWA之sql盲注

    写在前面 当时刷sqli labs也浑浑噩噩没有做啥总结 现在就先从sql盲注总结开始吧 SQL Injection Blind SQL盲注与一般注入的区别在于 一般的注入攻击者可以直接从页面上看到注入语句的执行结果 而盲注时攻击者通常是无
  • GPU处理图像 Shader的入门

    from http www jianshu com p 8687a040eb48 字数2901 阅读316 评论0 喜欢3 Shader着色器 Shader出现在OpenGL ES 2 0中 允许创建自己的Shader 必须同时创建两个Sh