2
0

GLSL.PhongShader.pas 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLSL.PhongShader;
  5. (* An ARBvp1.0 + ARBfp1.0 shader that implements phong shading. *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. System.Classes,
  12. System.SysUtils,
  13. GLS.Texture,
  14. Stage.VectorTypes,
  15. Stage.VectorGeometry,
  16. GLS.VectorLists,
  17. Stage.OpenGLTokens,
  18. GLS.Context,
  19. GLSL.AsmShader,
  20. GLS.RenderContextInfo,
  21. GLSL.CustomShader,
  22. GLS.State;
  23. type
  24. TGLPhongShader = class(TGLCustomAsmShader)
  25. private
  26. FLightIDs: TGLIntegerList;
  27. FDesignTimeEnabled: Boolean;
  28. FAmbientPass: Boolean;
  29. procedure SetDesignTimeEnabled(const Value: Boolean);
  30. protected
  31. procedure DoLightPass(lightID: Cardinal); virtual;
  32. procedure DoAmbientPass(var rci: TGLRenderContextInfo); virtual;
  33. procedure UnApplyLights(var rci: TGLRenderContextInfo); virtual;
  34. procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
  35. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  36. procedure DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject); override;
  37. public
  38. constructor Create(AOwner: TComponent); override;
  39. destructor Destroy; override;
  40. function ShaderSupported: Boolean; override;
  41. published
  42. property DesignTimeEnabled: Boolean read FDesignTimeEnabled write SetDesignTimeEnabled default False;
  43. end;
  44. //---------------------------------------------------------------
  45. implementation
  46. //---------------------------------------------------------------
  47. procedure TGLPhongShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
  48. begin
  49. if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
  50. GetActiveLightsList(FLightIDs);
  51. FAmbientPass := False;
  52. if FLightIDs.Count > 0 then
  53. begin
  54. rci.GLStates.DepthFunc := cfLEqual;
  55. rci.GLStates.Disable(stBlend);
  56. DoLightPass(FLightIDs[0]);
  57. FLightIDs.Delete(0);
  58. end
  59. else
  60. begin
  61. DoAmbientPass(rci);
  62. FAmbientPass := True;
  63. end;
  64. end;
  65. function TGLPhongShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
  66. begin
  67. Result := False;
  68. if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
  69. if FLightIDs.Count > 0 then
  70. begin
  71. UnApplyLights(rci);
  72. Result := True;
  73. Exit;
  74. end
  75. else
  76. if not FAmbientPass then
  77. begin
  78. Self.UnApplyShaderPrograms();
  79. rci.GLStates.Enable(stBlend);
  80. rci.GLStates.SetBlendFunc(bfOne, bfOne);
  81. DoAmbientPass(rci);
  82. FAmbientPass := True;
  83. Result := True;
  84. Exit;
  85. end;
  86. rci.GLStates.DepthFunc := cfLEqual;
  87. end;
  88. procedure TGLPhongShader.DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject);
  89. begin
  90. if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
  91. inherited;
  92. end;
  93. procedure TGLPhongShader.SetDesignTimeEnabled(const Value: Boolean);
  94. begin
  95. if Value <> FDesignTimeEnabled then
  96. begin
  97. FDesignTimeEnabled := Value;
  98. NotifyChange(Self);
  99. end;
  100. end;
  101. constructor TGLPhongShader.Create(AOwner: TComponent);
  102. begin
  103. inherited;
  104. with VertexProgram.Code do
  105. begin
  106. Add('!!ARBvp1.0');
  107. Add('OPTION ARB_position_invariant;');
  108. Add('PARAM mvinv[4] = { state.matrix.modelview.inverse };');
  109. Add('PARAM mvit[4] = { state.matrix.modelview.invtrans };');
  110. Add('PARAM lightPos = program.local[0];');
  111. Add('TEMP light, normal, eye;');
  112. Add(' ADD eye, mvit[3], -vertex.position;');
  113. Add(' MOV eye.w, 0.0;');
  114. Add(' DP4 light.x, mvinv[0], lightPos;');
  115. Add(' DP4 light.y, mvinv[1], lightPos;');
  116. Add(' DP4 light.z, mvinv[2], lightPos;');
  117. Add(' ADD light, light, -vertex.position;');
  118. Add(' MOV light.w, 0.0;');
  119. Add(' MOV result.texcoord[0], vertex.normal;');
  120. Add(' MOV result.texcoord[1], light;');
  121. Add(' MOV result.texcoord[2], eye;');
  122. Add('END');
  123. end;
  124. with FragmentProgram.Code do
  125. begin
  126. Add('!!ARBfp1.0');
  127. Add('PARAM lightDiff = program.local[0];');
  128. Add('PARAM lightSpec = program.local[1];');
  129. Add('PARAM materialDiff = state.material.diffuse;');
  130. Add('PARAM materialSpec = state.material.specular;');
  131. Add('PARAM shininess = state.material.shininess;');
  132. Add('TEMP temp, light, normal, eye, R, diff, spec;');
  133. Add(' DP3 temp, fragment.texcoord[0], fragment.texcoord[0];');
  134. Add(' RSQ temp, temp.x;');
  135. Add(' MUL normal, temp.x, fragment.texcoord[0];');
  136. Add(' DP3 temp, fragment.texcoord[1], fragment.texcoord[1];');
  137. Add(' RSQ temp, temp.x;');
  138. Add(' MUL light, temp.x, fragment.texcoord[1];');
  139. Add(' DP3 temp, fragment.texcoord[2], fragment.texcoord[2];');
  140. Add(' RSQ temp, temp.x;');
  141. Add(' MUL eye, temp.x, fragment.texcoord[2];');
  142. Add(' DP3_SAT diff, normal, light;');
  143. Add(' MUL diff, diff, lightDiff;');
  144. Add(' MUL diff, diff, materialDiff;');
  145. Add(' DP3 R, normal, light;');
  146. Add(' MUL R, R.x, normal;');
  147. Add(' MUL R, 2.0, R;');
  148. Add(' ADD R, R, -light;');
  149. Add(' DP3_SAT spec, R, eye;');
  150. Add(' POW spec, spec.x, shininess.x;');
  151. Add(' MUL spec, spec, lightDiff;');
  152. Add(' MUL spec, spec, materialDiff;');
  153. Add(' ADD_SAT result.color, diff, spec;');
  154. Add(' MOV result.color.w, 1.0;');
  155. Add('END');
  156. end;
  157. FLightIDs := TGLIntegerList.Create;
  158. end;
  159. function TGLPhongShader.ShaderSupported: Boolean;
  160. var
  161. MaxTextures: Integer;
  162. begin
  163. Result := inherited ShaderSupported and GL.ARB_multitexture;
  164. gl.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @MaxTextures);
  165. Result := Result and (maxTextures > 2);
  166. end;
  167. procedure TGLPhongShader.UnApplyLights(var rci: TGLRenderContextInfo);
  168. begin
  169. rci.GLStates.DepthFunc := cfLEqual;
  170. rci.GLStates.Enable(stBlend);
  171. rci.GLStates.SetBlendFunc(bfOne, bfOne);
  172. DoLightPass(FLightIDs[0]);
  173. FLightIDs.Delete(0);
  174. end;
  175. destructor TGLPhongShader.Destroy;
  176. begin
  177. FLightIDs.Free;
  178. inherited;
  179. end;
  180. procedure TGLPhongShader.DoAmbientPass(var rci: TGLRenderContextInfo);
  181. var
  182. ambient, materialAmbient: TGLVector;
  183. begin
  184. rci.GLStates.Disable(stLighting);
  185. gl.GetFloatv(GL_LIGHT_MODEL_AMBIENT, @ambient);
  186. gl.GetMaterialfv(GL_FRONT, GL_AMBIENT, @materialAmbient);
  187. ScaleVector(ambient, materialAmbient);
  188. gl.Color3fv(@ambient);
  189. end;
  190. procedure TGLPhongShader.DoLightPass(lightID: Cardinal);
  191. var
  192. LightParam: TGLVector;
  193. begin
  194. Self.ApplyShaderPrograms();
  195. with CurrentGLContext.GLStates do
  196. begin
  197. gl.GetLightfv(GL_LIGHT0+lightID, GL_POSITION, @LightParam);
  198. LightParam := LightParam;
  199. gl.ProgramLocalParameter4fv(GL_VERTEX_PROGRAM_NV, 0, @LightParam);
  200. LightParam := LightDiffuse[lightID];
  201. gl.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 0, @LightParam);
  202. LightParam := LightSpecular[lightID];
  203. gl.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 1, @LightParam);
  204. end;
  205. end;
  206. initialization
  207. RegisterClasses([TGLPhongShader]);
  208. end.