原文:HLSL效果框架-多光源效果


昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心

手机淘宝二维码 扫描      

或者打开连接:程序设计开发 ,掌声鼓励,欢迎光临.


 

 

高级着色器语言(HLSL)难就难在它是运行在GPU,CPU上的,编写和调试都很麻烦.

用效果框架简化了很多操作,先列出着色器的代码,重点部分都用中文注释了

着色器语言文件为:,代码为:

  1. //着色器处理未知数量光源数目 未知光源种类 的 混合效果
  2. //HLSL里一共支持256个float4,一个int最后也转成float4,float4x3和float3x3占内存一样,最终都变成float4
  3. //因为HLSL的限制条件非常零散也非常多,所以,用起来还是很吃力的,在不懂的情况下,
  4. //最终指令不能超过500多条貌似,运行在显卡中程序,所以能省则省,能精简则精简!!!
  5. //
  6. //结构体 注意:为了优化结构,把一些相关参数整合到了一起
  7. //
  8. struct PointLight //点光源 结构
  9. {
  10. float4 Diffuse; //漫反射的颜色r,g,b,a
  11. float4 Specular; //镜面高光的颜色r,g,b,a
  12. float4 Position; //光源位置x,y,z,w没用到
  13. float4 RangeAttenuation;//范围,恒定衰减,光强,二次衰减
  14. };
  15. struct DirectLight //方向光 结构
  16. {
  17. float4 Diffuse; //漫反射的颜色r,g,b,a
  18. float4 Specular; //镜面高光的颜色r,g,b,a
  19. float4 Direction; //方向x,y,z,高光
  20. };
  21. struct SpotLight //聚光灯 结构
  22. {
  23. float4 Diffuse; //漫反射的颜色r,g,b,a
  24. float4 Specular; //镜面高光的颜色r,g,b,a
  25. float4 Position; //光源位置x,y,z,w没用到
  26. float4 Direction; //方向x,y,z,w没用到
  27. float4 RangeAttenuation;//范围,恒定衰减,光强,二次衰减
  28. float4 FalloffThetaPhi; //从内锥到外锥之间的强度衰减,y没用到,内锥的弧度,外锥的弧度
  29. };
  30. //接收光源的数量
  31. int g_NumPLs; //程序里定义了几个点光源?
  32. int g_NumDLs; //程序里定义了几个方向光源?
  33. int g_NumSLs; //程序里定义了几个方向光源?
  34. PointLight g_PLs[10]; //定义最多支持10个点光源
  35. DirectLight g_DLs[10]; //定义最多支持10个方向光源
  36. SpotLight g_SLs[10]; //定义最多支持10个聚光灯光源
  37. //环境光(对于多灯光的场合,对每一个灯光循环进行这些运算(环境光除外))
  38. //最后加上环境光(假设只有一个环境光)
  39. matrix g_WorldMatrix;//世界矩阵
  40. float4 g_ViewPos;//观察点(相机)
  41. matrix WVPMatrix; //世界-观察-投影矩阵
  42. float AmbAmount; //环境光的强弱程度,介于0-1之间
  43. float4 AmbCol = { 1.0f, 1.0f, 1.0f, 1.0f };//环境光的颜色,默认白色
  44. //--------------------------------------------------------------------------
  45. // 顶点着色器(注意看下面,我把顶点着色器的输出顶点位置和法线,当作像素着色器的输入了!!!
  46. // TEXCOORD这类寄存器也没啥用,用来保存顶点和法线数据最合适不过了,最多好像是15个)
  47. //--------------------------------------------------------------------------
  48. struct VS_INPUT //输入结构
  49. {
  50. float4 position : POSITION;//输入:坐标
  51. float3 normal : NORMAL; //输入:法线
  52. };
  53. struct VS_OUTPUT //输出结构
  54. {
  55. float4 position : POSITION;
  56. float4 vtpos : TEXCOORD0;//传入像素着色器用,TEXCOORD表示寄存器名字,(实际上保存的数据当像素着色器的输入坐标用,用TEXCOORD,一方面是多,二方面没啥用)
  57. float3 normal : TEXCOORD1;
  58. };
  59. VS_OUTPUT VS_Main(VS_INPUT input)
  60. {
  61. VS_OUTPUT output = (VS_OUTPUT)0;
  62. output.vtpos = input.position;//模型本地空间坐标
  63. output.position = mul(input.position, WVPMatrix);//输出:世界-观察-投影变幻后的坐标
  64. output.normal = input.normal;
  65. return output;
  66. }
  67. //--------------------------------------------------------------------------
  68. // 像素着色器(COLOR0是必须输出的,其他的可作任何用途)
  69. //--------------------------------------------------------------------------
  70. struct PS_INPUT //输入
  71. {
  72. float4 vtpos : TEXCOORD0;//顶点位置(接受顶点着色器的输出,要对应)
  73. float3 normal : TEXCOORD1;
  74. };
  75. struct PS_OUTPUT //输出像素颜色
  76. {
  77. float4 Color : COLOR0; //像素着色器最终输出计算好的颜色
  78. };
  79. PS_OUTPUT PS_Main(PS_INPUT input)
  80. {
  81. PS_OUTPUT output = (PS_OUTPUT)0;
  82. float4 worldpos = mul(input.vtpos, g_WorldMatrix);//顶点在世界空间中的坐标,即乘以世界矩阵
  83. float4 colRes;//用于保存最终的颜色 = E环境光+自身光+E(点光+方向光+聚光); 其中点,方向,聚光 又包含漫反射,镜面反射
  84. float4 ambient = { 0.0f, 0.0f, 0.0f, 1.0f };//总环境光
  85. float4 self = { 0.0f, 0.0f, 0.0f, 1.0f };//自发光
  86. float4 diffuse = { 0.0f, 0.0f, 0.0f, 1.0f };//总漫反射光
  87. float4 specular = { 0.0f, 0.0f, 0.0f, 1.0f };//总镜面反射
  88. ambient = AmbCol * AmbAmount;//求出环境光
  89. for (int i = 0; i < g_NumPLs; i++)//点光源
  90. {
  91. float3 dirSize = input.vtpos.xyz - g_PLs[i].Position.xyz;//光源到顶点的方向和大小.光源→顶点pos
  92. float distance = length(dirSize);//距离
  93. float3 dir = normalize(dirSize);//单位化方向
  94. if (distance < g_PLs[i].RangeAttenuation.x)//顶点在灯光范围内
  95. {
  96. //求出漫反射
  97. float difusefactor = dot(dir.xyz, input.normal.xyz);
  98. if (difusefactor < 0)
  99. {
  100. difusefactor = 0;
  101. }
  102. float distanceDec = 1.0f - 1.0f / g_PLs[i].RangeAttenuation.x * distance;
  103. //漫反射 = diffuse*漫反射因子*距离衰减
  104. diffuse.xyz += g_PLs[i].Diffuse.xyz * difusefactor * distanceDec;//最后要乘以材质的吸收系数(这里没乘)
  105. //下面求镜面反射(镜面反射的算法自己去百度找吧...)
  106. float3 DirectionToView = normalize(worldpos.xyz - g_ViewPos.xyz); //(同在世界空间中!)
  107. float3 VectorToLight = normalize(input.vtpos.xyz - g_PLs[i].Position.xyz);
  108. //计算反射光
  109. float3 reflectanceRay = 2 * dot(input.normal.xyz, VectorToLight.xyz)*input.normal.xyz - VectorToLight.xyz;
  110. float specfactor = pow(abs(dot(reflectanceRay, DirectionToView)), g_PLs[i].RangeAttenuation.z);
  111. //镜面光累加
  112. specular.xyz += g_PLs[i].Specular.xyz * specfactor;//最后要乘以材质的吸收系数(这里没乘)
  113. }
  114. //else在光线外,无此光照影响
  115. }
  116. for (int j = 0; j < g_NumDLs; j++)//方向光源
  117. {
  118. //漫反射
  119. float3 dir = normalize(g_DLs[j].Direction.xyz);//单位化方向(光的方向)
  120. float difusefactor = dot(dir.xyz, input.normal.xyz);
  121. if (difusefactor < 0)
  122. {
  123. difusefactor = 0;
  124. }
  125. diffuse.xyz += g_DLs[j].Diffuse.xyz * difusefactor;//最后要乘以材质的吸收系数(这里没乘)
  126. //镜面反射
  127. float3 DirectionToView = normalize(worldpos.xyz - g_ViewPos.xyz);//观察点→顶点 (同在世界空间中!)
  128. //dir 已有
  129. //计算反射光
  130. float3 reflectanceRay = 2 * dot(input.normal.xyz, dir.xyz)*input.normal.xyz - dir.xyz;
  131. float specfactor = pow(abs(dot(reflectanceRay, DirectionToView)), g_DLs[j].Direction.w);
  132. //镜面光累加
  133. specular.xyz += g_DLs[j].Specular.xyz * specfactor;//最后要乘以材质的吸收系数(这里没乘)
  134. }
  135. for (int k = 0; k < g_NumSLs; k++)//聚光灯
  136. {
  137. float disdec = 0.0f;//距离衰减
  138. float raddec = 0.0f;//角度衰减
  139. float distance = length(g_SLs[k].Position.xyz - worldpos.xyz);//光源到顶点的距离
  140. float3 xconeDirection = normalize(g_SLs[k].Direction.xyz);//聚光灯方向
  141. float3 ltvdir = normalize(g_SLs[k].Position.xyz - worldpos.xyz);//光到顶点的方向
  142. float cosx = abs(dot(xconeDirection, ltvdir));//夹角的余弦值
  143. float cosPhi = cos(g_SLs[k].FalloffThetaPhi.w / 2.0f);
  144. float cosTheta = cos(g_SLs[k].FalloffThetaPhi.z / 2.0f);
  145. //距离衰减因子
  146. float sss = 1.0f / g_SLs[k].RangeAttenuation.x;
  147. if (cosx>cosTheta)//本影(角度衰减: 不衰减)
  148. {
  149. raddec = 1.0f;
  150. if (distance*cosx <g_SLs[k].RangeAttenuation.x)//在射程范围内
  151. {
  152. disdec = 1.0f - 1.0f / g_SLs[k].RangeAttenuation.x*distance*cosx;//距离衰减(线性衰减)
  153. }
  154. }
  155. if (cosx < cosTheta)//本影外(角度衰减: 急剧衰减 )
  156. {
  157. float v1 = cosx - cosPhi;
  158. float v2 = cosTheta - cosPhi;
  159. float v3 = v1 / v2;
  160. raddec = pow(abs(v3), g_SLs[k].FalloffThetaPhi.x);
  161. if (distance*cosx <g_SLs[k].RangeAttenuation.x)//在射程范围内(无光)
  162. {
  163. disdec = 1.0f - 1.0f / g_SLs[k].RangeAttenuation.x*distance*cosx; //距离衰减(线性衰减)
  164. }
  165. }
  166. if (cosx<cosPhi)//光锥外
  167. {
  168. raddec = 0.0f;
  169. }
  170. //计算漫反射
  171. float difusefactor = dot(ltvdir.xyz, input.normal.xyz);
  172. if (difusefactor < 0.0f)
  173. {
  174. difusefactor = 0.0f;
  175. }
  176. diffuse.xyz += g_SLs[k].Diffuse.xyz * raddec * disdec * difusefactor;//最后要乘以材质的吸收系数(这里没乘)
  177. //计算镜面反射
  178. float3 DirectionToView = normalize(worldpos.xyz - g_ViewPos.xyz);//观察点→顶点 (同在世界空间中!)
  179. float3 VectorToLight = normalize(input.vtpos.xyz - g_SLs[k].Position.xyz);
  180. //计算反射光
  181. float3 reflectanceRay = 2 * dot(input.normal.xyz, VectorToLight.xyz)*input.normal.xyz - VectorToLight.xyz;
  182. float specfactor = pow(abs(dot(reflectanceRay, DirectionToView)), g_SLs[k].RangeAttenuation.z);
  183. //镜面光累加
  184. specular.xyz += g_SLs[k].Specular.xyz * raddec * disdec * specfactor;//最后要乘以材质的吸收系数(这里没乘)
  185. }
  186. output.Color.w = 1.0f;//因为output被初始化为(PS_OUTPUT)0,w也初始化为0了.
  187. output.Color.xyz = ambient.xyz + self.xyz + diffuse.xyz + specular.xyz;//把所有种类的光都累加起来
  188. return output;
  189. }
  190. //--------------------------------------------------------------------------
  191. // 框架效果
  192. //--------------------------------------------------------------------------
  193. technique MulLights
  194. {
  195. pass P0
  196. {
  197. vertexShader = compile vs_3_0 VS_Main();//顶点着色器
  198. pixelshader = compile ps_3_0 PS_Main();//像素着色器
  199. }
  200. }

值得注意的是,环境光也可以有好几个(这里假设只有一个),另外,光照的最终叠加效果公式为:

最终光照颜色 = 所有的环境光 * 材质吸收指数 + 自发光 + (点光源 + 方向光源+聚光灯) * (漫反射 + 镜面反射) *材质吸收指数        

(自己推算的公式,可能有误,欢迎批评指出)

 

然后是应用程序中的代码:

变量定义:

D3DXMATRIX m_ProjMatrix; //投影矩阵

 D3DXMATRIX m_ViewMatrix; //观察矩阵

 //四个模型

 ID3DXMesh*    m_Meshes[4];

 D3DXMATRIX    m_WorldMatrices[4];

 D3DXVECTOR4    m_MeshColors[4];

 D3DMATERIAL9   m_Material;

 //点光源

 PointLight    m_PointLight[10];

 DirectLight   m_DirectLight[10];

 SpotLight    m_SpotLight[10];

 //-----------顶点着色器相关------------------

 D3DXHANDLE   m_WVPMatrixHandle;//世界-观察-投影矩阵句柄

 //-----------效果框架-----------------

 ID3DXEffect*   m_NLightEffect = 0;

 //-----------------句柄------------------------

 D3DXHANDLE    m_TecniMulLightsHandle = 0; //技术句柄

 D3DXHANDLE    m_AmbAmountHandle = 0;  //环境光系数句柄

  //各种光源句柄

 D3DXHANDLE    m_PointLHandle = 0;   //点光源句柄

 D3DXHANDLE    m_DirectLightHandle = 0; //方向光句柄

 D3DXHANDLE    m_SpotLightHandle = 0;  //聚光灯句柄

  //各种光源数量句柄

 D3DXHANDLE    m_NumPointLightHandle = 0; //点光源个数句柄

 D3DXHANDLE    m_NumDirectLightHandle = 0; //方向光个数句柄

 D3DXHANDLE    m_NumSpotLightHandle = 0; //聚光灯个数句柄

 D3DXHANDLE    m_ViewPosHandle = 0;  //观察点句柄

 D3DXHANDLE    m_WorldMatrixHandle = 0; //世界矩阵句柄

 

  1. #define MESH_TEAPOT 0
  2. #define MESH_SPHERE 1
  3. #define MESH_TORUS 2
  4. #define MESH_CYLINDER 3
  5. typedef D3DXVECTOR4 float4; //这里typedef成float4,就能与着色器里面一致,不需要改代码了!
  6. struct PointLight
  7. {
  8. float4 Diffuse; //漫反射的颜色
  9. float4 Specular; //镜面高光的颜色
  10. float4 Position; //光源位置
  11. float4 RangeAttenuation;//范围,恒定衰减,镜面光强弱,二次衰减
  12. };
  13. struct DirectLight
  14. {
  15. float4 Diffuse; //漫反射的颜色
  16. float4 Specular; //镜面高光的颜色
  17. float4 DirectionPow; //方向x,y,z,高光
  18. };
  19. struct SpotLight
  20. {
  21. float4 Diffuse; //漫反射的颜色
  22. float4 Specular; //镜面高光的颜色
  23. float4 Position; //光源位置
  24. float4 Direction; //方向
  25. float4 RangeAttenuation;//范围,恒定衰减,镜面光强弱,二次衰减
  26. float4 FalloffThetaPhi; //从内锥到外锥之间的强度衰减,NULL,内锥的弧度,外锥的弧度
  27. };

 

  1. //setup: main函数中调用一次
  2. void Setup()
  3. {
  4. HRESULT hr = 0;
  5. //创建模型们: 茶壶 圆球 圆环 圆桶
  6. D3DXCreateTeapot(m_d3dDevice->GetD3DDevice(), &m_Meshes[MESH_TEAPOT], NULL);
  7. D3DXCreateSphere(m_d3dDevice->GetD3DDevice(), 1.0f, 20, 20, &m_Meshes[MESH_SPHERE], NULL);
  8. D3DXCreateTorus(m_d3dDevice->GetD3DDevice(), 0.5f, 1.0f, 20, 20, &m_Meshes[MESH_TORUS], NULL);
  9. D3DXCreateCylinder(m_d3dDevice->GetD3DDevice(), 0.5f, 0.5f, 2.0f, 20, 20, &m_Meshes[MESH_CYLINDER], NULL);
  10. //模型们的在世界中的矩阵:
  11. D3DXMatrixTranslation(&m_WorldMatrices[MESH_TEAPOT], 0.0f, 2.0f, 0.0f);
  12. D3DXMatrixTranslation(&m_WorldMatrices[MESH_SPHERE], 0.0f, -2.0f, 0.0f);
  13. D3DXMatrixTranslation(&m_WorldMatrices[MESH_TORUS], -3.0f, 0.0f, 0.0f);
  14. D3DXMatrixTranslation(&m_WorldMatrices[MESH_CYLINDER], 3.0f, 0.0f, 0.0f);
  15. //模型们的颜色:
  16. m_MeshColors[MESH_TEAPOT] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
  17. m_MeshColors[MESH_SPHERE] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
  18. m_MeshColors[MESH_TORUS] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
  19. m_MeshColors[MESH_CYLINDER] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
  20. //
  21. //创建两个点光源
  22. //m_PointLight[0]
  23. m_PointLight[0].Diffuse = { 1.0f, 0.0f, 0.0f, 1.0f };//Diffuse
  24. m_PointLight[0].Specular = { 1.0f, 1.0f, 1.0f, 1.0f };//Specular
  25. m_PointLight[0].Position = { -6.0f, 2.0f, 2.0f, 0.0f };//Position
  26. m_PointLight[0].RangeAttenuation = { 15.0f, 1.0f, 50.0f, 0.0f };//Range,Attenuation0,镜面光强弱,Attenuation2
  27. //m_PointLight[1]
  28. m_PointLight[1].Diffuse = { 0.0f, 1.0f, 0.0f, 1.0f };
  29. m_PointLight[1].Specular = { 1.0f, 1.0f, 1.0f, 1.0f };
  30. m_PointLight[1].Position = { 6.0f, 2.0f, 3.0f, 0.0f };
  31. m_PointLight[1].RangeAttenuation = { 15.0f, 0.8f, 50.0f, 0.0f };
  32. //创建一个方向光
  33. //m_DirectLight[0]
  34. m_DirectLight[0].Diffuse = { 0.5f, 0.5f, 0.5f, 1.0f };
  35. m_DirectLight[0].Specular = { 0.5f, 0.5f, 0.5f, 1.0f };
  36. m_DirectLight[0].DirectionPow = { 0.0f, 0.0f, -1.0f, 10.0f };//(z轴正方向)
  37. //创建一个聚光灯
  38. //m_SpotLight[0]
  39. m_SpotLight[0].Diffuse = { 1.0f, 1.0f, 1.0f, 1.0f };
  40. m_SpotLight[0].Specular = { 1.0f, 1.0f, 1.0f, 1.0f };
  41. m_SpotLight[0].Position = { 0.0f, 1.8f, -5.0f, 0.0f };
  42. m_SpotLight[0].Direction = { 0.0f, 0.0f, 1.0f, 0.0f };
  43. m_SpotLight[0].FalloffThetaPhi = { 3.5f, 0.0f, 0.04f, 0.18f };//衰减,-,内角(弧度半角),外角(弧度半角)
  44. m_SpotLight[0].RangeAttenuation = { 10.0f, 0.0f, 20.0f, 0.0f };//范围,衰减1,高光,衰减2
  45. ID3DXBuffer* errorBuffer = 0;
  46. hr = D3DXCreateEffectFromFile(m_d3dDevice->GetD3DDevice(),
  47. L"D:\\nlight.fx",
  48. 0,
  49. 0,
  50. D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY,
  51. 0,
  52. &m_NLightEffect,
  53. &errorBuffer);
  54. // 输出错误信息:
  55. if (errorBuffer)
  56. {
  57. string str = (char*)errorBuffer->GetBufferPointer();
  58. MessageBox(NULL, Common::StringToWString(str).c_str(), L"ERROR", MB_OK);
  59. //safe_release<ID3DXBuffer*>(error_buffer);
  60. }
  61. if (FAILED(hr))
  62. {
  63. MessageBox(NULL, L"D3DXCreateEffectFromFile() - FAILED", L"ERROR", MB_OK);
  64. }
  65. //获取hlsl中常量句柄
  66. //得到技术technique MulLights的句柄
  67. m_TecniMulLightsHandle = m_NLightEffect->GetTechniqueByName("MulLights");
  68. //各种光源的个数
  69. m_NumPointLightHandle = m_NLightEffect->GetParameterByName(NULL, "g_NumPLs");
  70. m_NumDirectLightHandle = m_NLightEffect->GetParameterByName(NULL, "g_NumDLs");
  71. m_NumSpotLightHandle = m_NLightEffect->GetParameterByName(NULL, "g_NumSLs");
  72. //获取光源种类的句柄
  73. m_AmbAmountHandle = m_NLightEffect->GetParameterByName(NULL, "AmbAmount");//环境光因子句柄
  74. m_PointLHandle = m_NLightEffect->GetParameterByName(NULL, "g_PLs");//点光源句柄
  75. m_DirectLightHandle = m_NLightEffect->GetParameterByName(NULL, "g_DLs");//方向光句柄
  76. m_SpotLightHandle = m_NLightEffect->GetParameterByName(NULL, "g_SLs");//聚光灯句柄
  77. //获取观察点,矩阵句柄
  78. m_ViewPosHandle = m_NLightEffect->GetParameterByName(NULL, "g_ViewPos");
  79. m_WorldMatrixHandle = m_NLightEffect->GetParameterByName(NULL, "g_WorldMatrix");
  80. m_WVPMatrixHandle = m_NLightEffect->GetParameterByName(NULL, "WVPMatrix");//世界观察投影矩阵
  81. //设置常量句柄
  82. //传光源数据进去
  83. m_NLightEffect->SetRawValue(m_PointLHandle, m_PointLight, 0,sizeof(PointLight)*2);//传点光源
  84. m_NLightEffect->SetRawValue(m_DirectLightHandle, m_DirectLight, 0, sizeof(DirectLight)* 1);//传方向光
  85. m_NLightEffect->SetRawValue(m_SpotLightHandle, m_SpotLight, 0, sizeof(SpotLight)* 1);//传聚光灯
  86. m_NLightEffect->SetFloat(m_AmbAmountHandle, 0.0f);
  87. m_NLightEffect->SetInt(m_NumPointLightHandle, 2);//点光源数量:2 (调节个数可方便调试)
  88. m_NLightEffect->SetInt(m_NumDirectLightHandle, 1);//方向光数量:1
  89. m_NLightEffect->SetInt(m_NumSpotLightHandle, 1);//聚光灯数量:1
  90. //设置投影矩阵
  91. RECT rt;
  92. GetClientRect(Application::GetInstance()->GetWnd(), &rt);
  93. D3DXMatrixPerspectiveFovLH(&m_ProjMatrix, D3DX_PI / 4.0f, (float)rt.right / rt.bottom, 1.0f, 1000.0f);
  94. //暂时未设置纹理
  95. m_d3dDevice->GetD3DDevice()->SetRenderState(D3DRS_LIGHTING, false);//关闭灯光,即不用固定管线
  96. }

 

  1. //display: 在消息循环中调用,时时更新
  2. void Display(float timeDelta)
  3. {
  4. static float angle = (3.0f * D3DX_PI) / 2.0f;
  5. static float height = 0.0f;
  6. if (GetAsyncKeyState(VK_LEFT) & 0x8000f)
  7. angle -= 0.5f * timeDelta;
  8. if (GetAsyncKeyState(VK_RIGHT) & 0x8000f)
  9. angle += 0.5f * timeDelta;
  10. if (GetAsyncKeyState(VK_UP) & 0x8000f)
  11. height += 5.0f * timeDelta;
  12. if (GetAsyncKeyState(VK_DOWN) & 0x8000f)
  13. height -= 5.0f * timeDelta;
  14. //求出观察矩阵
  15. D3DXVECTOR3 position(cosf(angle) * 7.0f, height, sinf(angle) * 7.0f);
  16. D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
  17. D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
  18. D3DXMatrixLookAtLH(&m_ViewMatrix, &position, &target, &up);
  19. D3DXVECTOR4 vps = { cosf(angle) * 7.0f, height, sinf(angle) * 7.0f, 0.0f };
  20. m_NLightEffect->SetVector(m_ViewPosHandle, &vps);
  21. // render now
  22. m_d3dDevice->GetD3DDevice()->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x99999999, 1.0f, 0);
  23. m_d3dDevice->GetD3DDevice()->BeginScene();
  24. //设置技术
  25. m_NLightEffect->SetTechnique(m_TecniMulLightsHandle);
  26. D3DXMATRIX WVPMatrix;
  27. for (int i = 0; i < 4; i++)
  28. {
  29. WVPMatrix = m_WorldMatrices[i] * m_ViewMatrix * m_ProjMatrix;
  30. m_NLightEffect->SetMatrix(m_WorldMatrixHandle, &m_WorldMatrices[i]);
  31. m_NLightEffect->SetMatrix(m_WVPMatrixHandle, &WVPMatrix);
  32. UINT numPass = 0;
  33. m_NLightEffect->Begin(&numPass, 0);
  34. for (UINT j = 0; j < numPass; ++j)
  35. {
  36. //开始过程
  37. m_NLightEffect->BeginPass(j); //在begin和end中间不建议设置着色器变量
  38. m_Meshes[i]->DrawSubset(0);
  39. //结束过程
  40. m_NLightEffect->EndPass();
  41. }
  42. //结束使用技术
  43. m_NLightEffect->End();
  44. }
  45. m_d3dDevice->GetD3DDevice()->EndScene();
  46. m_d3dDevice->GetD3DDevice()->Present(NULL, NULL, NULL, NULL);
  47. }

测试一: 1个点光源:

发现了一个错误!!!:黑色的地方没有光照,居然也有镜面反射了,oh,shit,网上的算法也不严谨嘛...

解决方法:稍微一思考,有光的地方才有镜面反射对吧?怎么样才有光? 就是光线方向和面法线的夹角要大于0,

即difusefactor = dot(光线,面法线)>0.0f; 即difusefactor>0.0f,所以,HLSL里在计算镜面光的时候多加一个

判断:

//镜面反射算法

   if (difusefactor>0.0f) //只有有光照到的地方才有镜面反射!!!

   {

    float3 DirectionToView = normalize(worldpos.xyz - g_ViewPos.xyz);  //(同在世界空间中!)

     float3 VectorToLight = normalize(input.vtpos.xyz - g_PLs[i].Position.xyz);

     //计算反射光

     float3 reflectanceRay = 2 * dot(input.normal.xyz, VectorToLight.xyz)*input.normal.xyz - VectorToLight.xyz;

     float specfactor = pow(abs(dot(reflectanceRay, DirectionToView)), g_PLs[i].RangeAttenuation.z);

    //镜面光累加

    specular.xyz += g_PLs[i].Specular.xyz * specfactor;//最后要乘以材质的吸收系数(这里没乘)

   }  

(下面的效果图都没有修改这一个错误,自行修改)

测试二: 两个点光源:

测试三: 方向光:

测试四:聚光灯:

测试五:火力全开:

(亮瞎眼了~...)





HLSL效果框架-多光源效果的更多相关文章

  1. HLSL效果框架

    原文:HLSL效果框架 HLSL效果框架能简化许多操作.这里先不写具体的效果框架的程序,在处理多光源光照的时候再整理. 下一章:效果框架-多种光源的多光源 叠加效果 这儿先列出效果框架的一个注意点: ...

  2. GooglePlay 首页效果----tab的揭示效果(Reveal Effect) (1)

    GooglePlay 首页效果----tab的揭示效果(Reveal Effect) (1) 前言: 无意打开GooglePlay app来着,然后发现首页用了揭示效果,连起来用着感觉还不错. 不清楚 ...

  3. 【转】提示框第三方库之MBProgressHUD iOS toast效果 动态提示框效果

    原文网址:http://www.zhimengzhe.com/IOSkaifa/37910.html MBProgressHUD是一个开源项目,实现了很多种样式的提示框,使用上简单.方便,并且可以对显 ...

  4. 设置TextView的密码效果以及跑马灯效果

    密码效果以及跑马灯效果: xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...

  5. 页面倒计时跳转页面效果,js倒计时效果

    页面倒计时跳转页面效果,js倒计时效果 >>>>>>>>>>>>>>>>>>>> ...

  6. 6 cocos2dx粒子效果,类图关系,系统原生粒子和自己定义粒子效果,粒子编译器软件,爆炸粒子效果,烟花效果,火焰效果,流星效果,漩涡粒子效果,雪花效果,烟雾效果,太阳效果,下雨效果

     1 粒子 演示样例 2 类图关系 3 系统原生粒子 CCParticleSystem 全部粒子系统的父类 CCParticleSystemPoint. CCParticleSystemQuad ...

  7. 有一段<script>代码,效果是点击<p>就会弹出信息,但是有的<p>点击会有效果,有的没有效果

    问题:有一段<script>代码,效果是点击<p>就会弹出信息,但是有的<p>点击会有效果,有的没有效果 解决: 页面代码是至上而下执行的,如果你的这个标签在< ...

  8. 多种效果进度指示层效果iOS源码项目

    该源码是一个多种效果进度指示层效果源码案例,源码KVNProgress,KVNProgress提供多种效果的进度指示层,有半透明效果,也支持全屏显示.指示层还高度支持自定义,可以按自己的需求定制.效果 ...

  9. 一款简洁而强大的前端框架JQUery—动画效果及剪刀石头布小游戏

    jQuery是什么? jQuery是一个快速.简洁的JavaScript框架,它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作.事件处理.动画 ...

随机推荐

  1. 技术人自己的KPI

    为什么需要技术KPI 在业务技术团队,有一个不好的趋势,就是团队越来越业务,越来越没有技术味道.每个人都在谈业务,技术大会上在谈业务,周会上在聊业务,周报里写的是业务项目......唯独少被谈及的是技 ...

  2. [Array]189. Rotate Array

    Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array  ...

  3. div 无缝滚动

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org ...

  4. jframe 设置左上角和任务栏的图标

    默认就是 改成有意义的,一眼就能看出来功能的,比如一个小蜘蛛 第一个最简单的做法,把图片扔到工程的根目录,但是这样会相当乱,不便于文件管理 ImageIcon icon = new ImageIcon ...

  5. Web三大组件之控制器组件Servlet(转载)

    Servlet:主要用于处理客户端传来的请求,并返回响应.获取请求数据>处理请求>完成响应 过程:客户端发送请求----HTTP服务器接收请求,HTTP服务器只负责解析静态HTML界面,其 ...

  6. neo4j批量导入neo4j-import

    neo4j数据批量导入 1 neo4j基本参数 1.1 启动与关闭: 1.2 neo4j-admin的参数:控制内存 1.2.1 memrec 是查看参考内存设置 1.2.2 指定缓存–pagecac ...

  7. CURL POST PHP

    function SendPostCurl($url,$post_data){ $curl = curl_init(); //初始化 curl_setopt($curl, CURLOPT_URL, $ ...

  8. 全面解析vue-cli生成的项目中使用其他库(js库、css库)

    前言:最近有小伙伴问我,是不是用vue脚手架生成的项目就不能jquery了呢?显然,答案是否定的,必须能用.但是个人建议最好不要用了,用人家vue提供的不好嘛. 一.用vue-cli生成项目 1. v ...

  9. Django 自定义auth_user

    1 导入AbstractUser from django.contrib.auth.models import AbstractUser 1 2 创建类UserProfile并继承AbstractUs ...

  10. Linux的概述与分类

    1.Linux的概述 Linux是基于Unix的开源免费的操作系统,由于系统的稳定性和安全性几乎成为程序代码运行的最佳系统环境.Linux是由Linus Torvalds(林纳斯·托瓦兹)起初开发的, ...