HLSL有关的基础知识
主要是最近在学习XNA中有关一些效果的东西,发现了官网上的2D的一些FX效果相当好。其代码给出如下链接http://creators.xna.com/en-US/sample/spriteeffects 然后就查了一下HLSL这个范例里面的FX还都不算太难,可以理解。
一个简单的HLSL程序,返回一个材质的各点的颜色。
sampler s0 : register(s0);
float4 main(float2 tex : TEXCOORD0) : COLOR
{
return tex2D(s0,tex);
}
HLSL,颜色表示。
使用MPC的custom shader,由于在MPC中需要使用HLSL编写shader,所以首先要了解HLSL里面的颜色表示法,HLSL中,尤其是MPC中,颜色基本都是使 用XRGB表示(X代表保留位),一般将其表示为一个四维矢量,数据类型是float4。比如float4 color;,那么接下来就可以用color.x,color.y,color.z,来分别访问R,G,B三个分量了。
众所周知,对于24位,或者32位图像来说来说,RGB每个通道都是8位,转化为10进制就是0-255的整数,不过在HLSL中情况不同,0对应的是 float(0.0)而255对应的是float(1.0),所以白色表示不再是(255,255,255)而是float3(1.0,1.0,1.0) 或者float4(1.0,1.0,1.0,1.0)。
程序解释
第一行定义了一个sampler,将pixel shader寄存器s0与我们定义的sampler s0绑定,在MPC中,寄存器s0就是影片图像所对应的纹理。
float4 main(float2 tex : TEXCOORD0) : COLOR,它代表的意思是,输出一个float4变量,将这个float4变量作为COLOR(作为render target 0中的颜色,关于render target,后面会解释)。这个函数有一个输入参数,就是作为0号纹理坐标(TEXCOORD0)的float2类型的tex。
HLSL中的最简单的2D纹理映射函数是tex2D(s,t);两个参数,第一个是一个sampler,它代表的是目标纹理和纹理过滤,寻址方式,第二个 参数是一个float2,也就是纹理坐标uv。它返回一个颜色值float4,这就是:纹理s中,纹理坐标t处的颜色之意。
在这里就需要说明作为输入的TEXCOORD0的内容了,在MPC中,我们知道原纹理要经过shader处理后写入一个新的同样大小的纹理中,所以事实上 它绘制了一个full rect quad(全区域矩形)并把新的纹理作为该次绘制的输出对象(即绘制的东西就不显示于屏幕上,而绘制到该纹理中)。
练习下看代码:
变亮20%
sampler s0 : register(s0);
float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 color0 = tex2D(s0,tex);
return color0+color0*float4(0.2,0.2,0.2,0.0);
}
常用MUL函数
上面color0*float4(0.2,0.2,0.2,0.0)是对位相乘。即:
color1 = color0*scale;
则代表
color1.x = color0.x*scale.x;
color1.y = color0.y*scale.y;
color1.z = color0.z*scale.z;
color1.w = color0.w*scale.w;
如果需要得到矢量点积,需要用mul(x,y);
比如float lum = mul(color0.xyz,float3(0.3,0.59,0.11) );其中color0.xyz表示以color0的xyz元素构成的一个3维向量,lum = color0.x*0.3 + color0.y*0.59 + color0.z*0.11;
读代码练习:
灰度转换shader
sampler s0 : register(s0);
float4 main(float2 tex : TEXCOORD0) : COLOR
{
float4 color0 = tex2D(s0,tex);
float lum = mul(color0.xyz,float3(0.3,0.59,0.11) );
return float4(lum,lum,lum,1.0);
}
HLSL的PS版本的问题
会用color0+color0*float4(0.2,0.2,0.2,0.0)而不是color0*float4(1.2,1.2,1.2,1.0) 是由于ps版本问题。版本越高,HLSL就越灵活,当然,硬件功能要求也就越强。对于ps1.x来说,常量寄存器不能储存超过1的数值,所以如果用 float4(1.2,1.2,1.2,1.0)运行时会直接当作float4(1.0,1.0,1.0,1.0)处理,也可以说,是HLSL编译器比较 弱智,不能自动转化为color0+color0*float4(0.2,0.2,0.2,0.0)。
(所以会看到wow为每个ps版本写了不同的代码。)
如何获得相邻像素
如下图,设原纹理大小为M*N个texel,于是每个texel的uv尺寸为(1.0/M,1.0/N),所以可以通过将tex偏移再tex2D来取得相邻处的texel。
GPU汇编指令
add——vec1+vec2——矢量对位相加
mul——vec1*vec2——矢量对位相乘
mad——vec1*vec2+vec3——矢量对位乘加
dp3——vec1.x*vec2.x+vec1.y*vec2.y+vec1.z*vec2.z——矢量点积
等运算,而标量单元负责的是诸如
pow——scar1^scar2——标量幂运算
rcp——1.0/scar1——标量倒数运算
rsq——1.0/sqrt(scar1)——标量方根倒数
log——log2(scar1)——2为底的对数
等等
而纹理单元,执行的自然是
texld——纹理采样函数
在MPC的HLSL编译目标(compile target)选项中,有意义的包括ps_1_1,ps_1_3,ps_1_4,ps_2_0,ps_3_0。HLSL code的结构复杂度、指令的复杂性、指令数多寡决定了它最低需要的编译目标。
ps_1_1和ps_1_3在实际应用中差别甚微。都属于限制非常大的编译目标,主要限制是:
1: 最大指令数目限制严重,不能超过8条算术指令(尽管其实可以不超过3维的矢量运算与标量运算并发(co-issue)所以最多是16条算术指令,但是不用 指望HLSL编译器能够强大到如此程度)和4条纹理指令(ps1.1-1.3的纹理指令其实比较复杂,属于组合功能方式,但是在MPC中基本用不上)
2:无复杂运算指令,诸如rcp,rsq,log,pow等全部没有
3:寄存器数值范围很窄,比如float s1 = 1.5 * s2;就会自动变成float s1 = 1.0 * s2;(也就是1.5超出了范围),只能写成float s1 = s2+0.5*s2;才能正确编译
4:无dependent texture read。而tex基本可以认为无法操作
5:分支什么的就基本不用指望了。除了像if(s1>0.0){s2 = 1.0;}else{s2 = 0.0;}这种极其简单的。
ps_1_1级别的硬件,比较流行的是Nvidia Geforce 3
ps_1_3级别的硬件,比较流行的是Nvidia Geforce 4Ti
ps_1_4比ps_1_3适应性广一些包括
1:最大指令数限制有所松动,算术指令翻倍,纹理指令翻2倍。
2:支持一定限度的dependent texture read(1级),tex可以进行一定程度的操作
ps_1_4级别的硬件,比较流行的是ATI Radeon8500,9000-9200
事实上,由于ps1.x属于定点数结构,所以有一些移位指令可以使用,比如mul_x2,add_x2代表将结果相加后左移一位,相当于乘二。这也是为何第六节的第四个程序有ps1.x版本的原因。不过说到底,ps1.x不是为HLSL准备的。
ps_2_0是HLSL诞生时的默认编译对象
1:支持绝大多数的HLSL函数。
2:64条算术指令,32条纹理指令,最多4级的dependent texture read
3:全部浮点流水线,数据范围精度增强。
4:尽管ps_2_0没有硬件支持的动态分支,不过可以实现一定程度的分支,只不过每个分支都要跑一遍。也就是效率不会很高
ps_2_0级别的硬件包括Nvidia GeforceFx系列(ps_2_a)ATI Radeon 9500及以上X700以下(ps_2_0)X700,X800,X850系列(ps_2_b)
ps_3_0是当前PC上的最高pixel shader版本
1:比ps_2_0增加了一些指令
2:硬件支持分支,循环
3:最大指令数大大增加,不再有纹理算术指令数量分配的限制
4:dependent texture read级数没有限制
ps_3_0级别硬件包括Nvidia Geforce 6系列,7系列,ATI Radeon X1xxx系列
所以,编写HLSL请考虑自身硬件的功能等级。
以下是一些简单的提升性能的考虑
1:如果可以,使用ps1.x编译对象能获得最佳性能,如果该HLSL code不能使用ps1.x编译对象,那么请使用可用的最高ps版本的编译对象,如Geforce6系列就请使用ps_3_0编译对象。
2:在许可的情况下尽量减少使用复杂运算指令,诸如pow,sin,cos,asin,acos,sqrt等。
3:对于Nvidia Geforce Fx和6系列,推荐将float(FP32)替换为half(FP16)以提高性能。
4:对于向量来说,选择需要的最小维数,比如能用float3(half3)就不要用float4(half4),能用标量就不要用矢量
5:动态分支不要太多,除非你用的是X1800XT……
HLSL有关的基础知识相关推荐
- HLSL 的基础知识
基础知识很重要,一定要抓牢! 一.数据类型: HLSL中的数据类型主要有:标准类型.向量.矩阵.和复杂数据类型几大类. 标准数据类型: 标准的数据类型有:bool ,int,half ,float,d ...
- 计算机图形渲染基础知识(个人笔记)
一,什么是计算机图形学 对于我个人来说,计算机图形学是用计算机来表示图形,并且运用复杂的数学运算来生成图形的一门科学. 二,计算机图形学能干什么? 计算机图形学能制作粒子特效,动画,渲染,虚拟显示,增 ...
- 嵌入式Linux的OTA更新,基础知识和实现
嵌入式Linux的OTA更新,基础知识和实现 OTA updates for Embedded Linux, Fundamentals and implementation 更新的需要 一旦嵌入式Li ...
- 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记
计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...
- 嵌入式linux编程,嵌入式Linux学习笔记 - 嵌入式Linux基础知识和开发环境的构建_Linux编程_Linux公社-Linux系统门户网站...
注:所有内容基于友善之臂Mini2440开发板 一.嵌入式Linux开发环境的构建 嵌入式开发一般分为三个步骤: 1.编译bootloader,烧到开发板 2.编译嵌入式Linux内核,烧到开发板 3 ...
- 《计算机网络应用基础》模拟试卷(六),《计算机与网络应用基础知识1》模拟试卷...
<计算机与网络应用基础知识1>模拟试卷 (4页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 <计算机与网络应用基础知识1& ...
- python向量计算库教程_NumPy库入门教程:基础知识总结
原标题:NumPy库入门教程:基础知识总结 视学算法 | 作者 知乎专栏 | 来源 numpy可以说是 Python运用于人工智能和科学计算的一个重要基础,近段时间恰好学习了numpy,pandas, ...
- python常用变量名_python基础知识整理
Python Python开发 Python语言 python基础知识整理 序言:本文简单介绍python基础知识的一些重要知识点,用于总结复习,每个知识点的具体用法会在后面的博客中一一补充程序: 一 ...
- 计算机基础知识掌握欠缺,《计算机基础知识》实验教学改革探讨.pdf
<计算机基础知识>实验教学改革探讨.pdf Science& TechnologyVision 科 技 视 界 科技 探·索·争鸣 计<算机基础知识>实验教学改革探讨 ...
最新文章
- (转载)Markdown基本语法
- [BUUCTF-pwn]——pwnable_orw
- Linux 系统命令 - pwd - 显示当前所在的位置
- deque与vector的主要区别
- 09 | 自编码器:让模型拥有属于自己的表达和语言
- wampserver集成环境和安装
- 你相信逛 B 站也能学编程吗?
- How to integrate iAD in your iOS App ?
- Easy Data Transform如何在Excel中删除重复的行?
- placeholder在不同浏览器下的表现及兼容方法 placeholder兼容
- 数据分析中的统计学基础知识
- [信息论与编码] 03. 离散信源、信源熵、联合熵、条件熵
- anime.js 图片位移动画_从零了解PS做gif动图的小知识小技巧(2):PS帧动画
- 蜗居(露骨争议电视剧《蜗居》...
- mysql 怎么区分大小写_MYSQL区分大小写
- 判定通视的计算法公式_水准仪的后视和前视怎么区别?计算公式是什么?
- 她做销售6年,从底薪3K转行程序员狂飙2W,用两年转行经历致想转行的你
- 基于 Python 的全国空气质量监测与可视化分析平台
- Macbook上打开多个终端的方法
- 剑指Offer三天挑战赛03~15