|
VS初步研究
——作者:ZH1110 研究VS,先看一下VS常用的汇编代码 加法 add d, s0, s1 d.x = s0.x + s1.x d.y = s0.y + s1.y d.z = s0.z + s1.z d.w = s0.w + s1.w 点积 dp3 d, s0, s1 d.x = d.y = d.z = d.w = s0.x*s1.x + s0.y*d1.y + s0.z*s1.z 取小值 max d, s0, s1 d.x = (s0.x >= s1.x) ? s0.x : s1.x d.y = (s0.y >= s1.y) ? s0.y : s1.y d.z = (s0.z >= s1.z) ? s0.z : s1.z d.w = (s0.w >= s1.w) ? s0.w : s1.w 取大值 min d, s0, s1 d.x = (s0.x < s1.x) ? s0.x : s1.x d.y = (s0.y < s1.y) ? s0.y : s1.y d.z = (s0.z < s1.z) ? s0.z : s1.z d.w = (s0.w < s1.w) ? s0.w : s1.w 转移 mov d, s0 d.x = s0.x d.y = s0.y d.z = s0.z d.w = s0.w 乘法 mul d, s0, s1 d.x = s0.x * s1.x d.y = s0.y * s1.y d.z = s0.z * s1.z d.w = s0.w * s1.w 取倒数 rcp d, s0 d.x = d.y = d.z = d.w = (s0.w == 0) ? unendlich : 1/s0.w 开方的倒数 rsq d, s0 d.x = d.y = d.z = d.w = (s0.w == 0) ? unendlich : 1/sqrt(abs(s0.w))
我们先研究一下SDK8的vertexshader例子,这是一个波浪效果。
它的上下波动及颜色的改变是用近似的三角函数—— 比泰勒级数方程:sin(x)=x-x^3/6+x^5/120-x^7/5040+x^9/362880 方程的四个系数在vb中设置为c10,c11 vSin = vec4(1, -1 / 6, 1 / 120, -1 / 5040) vCos = vec4(1, -1 / 2, 1 / 24, -1 / 720) g_dev.SetVertexShaderConstant 10, vSin, 1 g_dev.SetVertexShaderConstant 11, vCos, 1 汇编代码中开始的r4.x相当于数学方程的X,处理后的的r4.x,r5.x相当于方程的结果,c4.w为常数1(所有数的0次方都为1)
代码如下: ;计算sin和cos的级数 mov r5.x, c4.w ; d^0 mov r4.x, r4.x ; d^1 mul r5.y, r4.x, r4.x ; d^2 mul r4.y, r4.x, r5.y ; d^3 mul r5.z, r5.y, r5.y ; d^4 mul r4.z, r4.x, r5.z ; d^5 mul r5.w, r5.y, r5.z ; d^6 mul r4.w, r4.x, r5.w ; d^7 ;计算sin近似值: mul r4, r4, c10 ; sin dp4 r4.x, r4, c4.w ;计算cos近似值: mul r5, r5, c11 ; cos dp4 r5.x, r5, c4.w
比泰勒级数只在pi到-pi内有效,超出这个范围误差大的惊人!所以以上代码前还要将r4.x的值限制在pi到-pi范围内: ; Clamp theta to -pi..pi add r4.x, r4.x, c7.x ; 先将数值提高pi高度 mul r4.x, r4.x, c7.y ; 缩小比例1/2pi frc r4.xy, r4.x ; 取小数部分 mul r4.x, r4.x, c7.z ; 再放大比例2pi add r4.x, r4.x,-c7.x ; 数值降低-pi高度
完整代码: ; 注释: ;; c0-c3 - View+Projection matrix ;; c4.x - time ; c4.y - 0 ; c4.z - 0.5 ; c4.w - 1.0 ;; c7.x - pi ; c7.y - 1/2pi ; c7.z - 2pi ; c7.w - 0.05 ;; c10 - first 4 taylor coefficients for sin(x) ; c11 - first 4 taylor coefficients for cos(x) ; vertex shader version 1.0 vs.1.0 ; Decompress position mov r0.x, v0.x mov r0.y, v0.y ; 1 mov r0.z, v0.y mov r0.w, c4.w ; 1 ; Compute theta from distance and time mov r4.xz, r0 ; xz mov r4.y, c4.y ; y = 0 dp3 r4.x, r4, r4 ; 计算出的值为点到中心距离的平方—d^2 rsq r4.x, r4.x ; 开方的倒数 rcp r4.x, r4.x ; 再倒数得到距离d mul r4.xyz, r4, c4.x ; 随时间缩放 ; Clamp theta to -pi..pi add r4.x, r4.x, c7.x mul r4.x, r4.x, c7.y frc r4.xy, r4.x mul r4.x, r4.x, c7.z add r4.x, r4.x,-c7.x ; Compute first 4 values in sin and cos series mov r5.x, c4.w ; d^0 mov r4.x, r4.x ; d^1 mul r5.y, r4.x, r4.x ; d^2 mul r4.y, r4.x, r5.y ; d^3 mul r5.z, r5.y, r5.y ; d^4 mul r4.z, r4.x, r5.z ; d^5 mul r5.w, r5.y, r5.z ; d^6 mul r4.w, r4.x, r5.w ; d^7 mul r4, r4, c10 ; sin dp4 r4.x, r4, c4.w mul r5, r5, c11 ; cos dp4 r5.x, r5, c4.w ; 设置颜色 add r5.x, -r5.x, c4.w ; + 1.0 mul oD0, r5.x, c4.z ; * 0.5 ; 缩放高度 mul r0.y, r4.x, c7.w ; Transform position dp4 oPos.x, r0, c0 dp4 oPos.y, r0, c1 dp4 oPos.z, r0, c2 dp4 oPos.w, r0, c3
绒毛 绒毛的效果也是通过PS处理的,它将所有顶点沿其法向偏移一小短距离形成外壳然后用绒毛的贴图渲染,经过多次的偏移,渲染后就形成这样的效果。
'设置渲染透明 device.SetRenderState D3DRS_ALPHABLENDENABLE, True device.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA device.SetRenderState D3DRS_DESTBLEND, D3DBLEND_DESTALPHA '设置绒毛的材质贴图 device.SetTexture 0, pelo device.SetStreamSource 0, objVB, D3DX.GetFVFVertexSize(D3DFVF_VERTEX) device.SetIndices objIB, 0 '绒毛颜色设置为5号常量寄存器 registroA(0) = 0.4 registroA(1) = 0.4 registroA(2) = 0.4 registroA(3) = 0 device.SetVertexShaderConstant 5, registroA(0), 1 'numStrati为绒毛长度 For aus = 1 To numStrati '间隔涨大 registroA(0) = registro(0) + aus registroA(1) = registro(1) + aus registroA(2) = registro(2) + aus device.SetVertexShaderConstant 6, registroA(0), 1 'direzione vento(trasformo per inverso matrice) m = muoviObjF(1, 1, 1, 0, angoloX, 0, 0, 0, 0) D3DXMatrixInverse m, 0, m D3DXVec4Transform vettore, direzV, m '这个向量加上后绒毛上下抖动 registroA(0) = vettore.X * fattoreV * aus registroA(1) = vettore.Y * fattoreV * aus registroA(2) = vettore.Z * fattoreV * aus device.SetVertexShaderConstant 7, registroA(0), 1 '渲染 device.DrawIndexedPrimitive D3DPT_TRIANGLELIST, 0, oggetto.meshX.GetNumVertices, 0, oggetto.meshX.GetNumFaces Next aus
汇编代码很简单: ;vertex shader realizzato da RobyDx ;permette di visualizzare un oggetto distanziando i ;vertici in base alle normali ;c0-c3 Traspose (World x View x Proj) ;c5 colore ;c6 dilatamento ;c7 direzione vs.1.0 mul r0,v3,c6 add r0,v0,r0 add r0,r0,c7 m4x4 oPos, r0, c0 mov oD0,c5 mov oT0, v7 |