GLSL.ShaderSem.pas 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // This unit is part of the GLScene Engine, http://glscene.org
  2. //
  3. unit GLSL.ShaderSem;
  4. (*
  5. SEM shader : Spherical Environment Mapping
  6. The main idea of SEM is to get the UV coordinates (which are used to lookup the matCap texture)
  7. from the normal vector on the fragment instead of the original texture coordinates from the object.
  8. A material using SEM is very useful to highlight variations in the mesh: creases, bumps, even slow ondulations.
  9. It doesn't work that well on a cube, for instance. And does absolutely nothing on a sphere:
  10. SEM on a sphere is exactly the same as a planar projection of the matCap texture.
  11. At this time only one light source is supported
  12. *)
  13. interface
  14. {$I GLScene.inc}
  15. uses
  16. Winapi.OpenGLext,
  17. System.Classes,
  18. OpenGLTokens,
  19. GLScene,
  20. GLBaseClasses,
  21. GLState,
  22. GLContext,
  23. GLRenderContextInfo,
  24. GLVectorGeometry,
  25. GLCoordinates,
  26. GLTextureFormat,
  27. GLColor,
  28. GLTexture,
  29. GLMaterial,
  30. GLSL.Shader,
  31. GLS.ShaderCustom;
  32. Type
  33. (* Custom class for GLSLSEMShader.
  34. SEM Shader : Spherical Environment Mapping *)
  35. TGLCustomGLSLSemShader = class(TGLCustomGLSLShader)
  36. private
  37. FAmbientColor: TGLColor;
  38. // FDiffuseColor: TGLColor;
  39. FSpecularColor: TGLColor;
  40. FAmbientFactor : Single;
  41. FDiffuseFactor : Single;
  42. FSpecularFactor : Single;
  43. FMaterialLibrary: TGLAbstractMaterialLibrary;
  44. FMainTexture: TGLTexture;
  45. FMainTexName : TGLLibMaterialName;
  46. // FSpecularPower: Single;
  47. // FLightPower: Single;
  48. function GetMaterialLibrary: TGLAbstractMaterialLibrary;
  49. procedure SetMainTexTexture(const Value: TGLTexture);
  50. function GetMainTexName: TGLLibMaterialName;
  51. procedure SetMainTexName(const Value: TGLLibMaterialName);
  52. //procedure SetDiffuseColor(AValue: TGLColor);
  53. procedure SetAmbientColor(AValue: TGLColor);
  54. procedure SetSpecularColor(AValue: TGLColor);
  55. protected
  56. procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
  57. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  58. procedure SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary); virtual;
  59. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  60. public
  61. constructor Create(AOwner : TComponent); override;
  62. destructor Destroy; override;
  63. // property DiffuseColor : TGLColor read FDiffuseColor Write setDiffuseColor;
  64. property SpecularColor : TGLColor Read FSpecularColor Write setSpecularColor;
  65. property AmbientColor : TGLColor Read FAmbientColor Write setAmbientColor;
  66. property AmbientFactor : Single Read FAmbientFactor Write FAmbientFactor;
  67. property DiffuseFactor : Single Read FDiffuseFactor Write FDiffuseFactor;
  68. property SpecularFactor : Single Read FSpecularFactor Write FSpecularFactor;
  69. property MaterialLibrary: TGLAbstractMaterialLibrary read getMaterialLibrary write SetMaterialLibrary;
  70. property MainTexture: TGLTexture read FMainTexture write SetMainTexTexture;
  71. property MainTextureName: TGLLibMaterialName read GetMainTexName write SetMainTexName;
  72. // property SpecularPower: Single read FSpecularPower write FSpecularPower;
  73. // property LightPower: Single read FLightPower write FLightPower;
  74. end;
  75. TGLSLSemShader = class(TGLCustomGLSLSemShader)
  76. published
  77. property AmbientColor;
  78. // property DiffuseColor;
  79. property SpecularColor;
  80. property AmbientFactor;
  81. property DiffuseFactor;
  82. property SpecularFactor;
  83. property MaterialLibrary;
  84. property MainTexture;
  85. property MainTextureName;
  86. end;
  87. //====================================================
  88. implementation
  89. //====================================================
  90. constructor TGLCustomGLSLSemShader.Create(AOwner: TComponent);
  91. begin
  92. inherited;
  93. with VertexProgram.Code do
  94. begin
  95. clear;
  96. Add('varying vec3 viewVec; ');
  97. Add('varying vec3 normal; ');
  98. Add('varying vec3 lightVec; ');
  99. Add('void main() { ');
  100. Add(' vec4 p = gl_ModelViewMatrix * gl_Vertex; ');
  101. Add(' vec4 lightPos = gl_LightSource[0].position;');
  102. Add(' lightVec = vec3(lightPos - p); ');
  103. Add(' viewVec = -vec3(p); ');
  104. Add(' normal = normalize(gl_NormalMatrix * gl_Normal ); ');
  105. Add(' gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; ');
  106. Add('} ');
  107. end;
  108. with FragmentProgram.Code do
  109. begin
  110. clear;
  111. Add('uniform vec4 AmbientColor; ');
  112. Add('uniform vec4 SpecularColor; ');
  113. Add('uniform float DiffuseIntensity; ');
  114. Add('uniform float AmbientIntensity; ');
  115. Add('uniform float SpecularIntensity; ');
  116. Add('uniform sampler2D MainTexture; ');
  117. Add('varying vec3 viewVec; ');
  118. Add('varying vec3 normal; ');
  119. Add('varying vec3 lightVec; ');
  120. Add('void main() { ');
  121. Add(' vec3 V = normalize(viewVec); ');
  122. Add(' vec3 r = reflect( V, normal ); ');
  123. Add(' float m = 2.0 * sqrt( pow( r.x, 2.0 ) + pow( r.y, 2.0 ) + pow( r.z + 1.0, 2.0 ) ); ');
  124. Add(' vec2 vN = r.xy / m + 0.5; ');
  125. Add(' vec4 DiffuseColor; ');
  126. Add(' DiffuseColor = texture2D( MainTexture, vN ); //.rgb; ');
  127. // Simple Lighting
  128. Add(' vec3 L = normalize(lightVec); ');
  129. Add(' vec3 halfAngle = normalize(L + V); ');
  130. Add(' float NdotL = dot(L, normal); ');
  131. Add(' float NdotH = clamp(dot(halfAngle, normal), 0.0, 1.0); ');
  132. Add(' // "Half-Lambert" technique for more pleasing diffuse term ');
  133. Add(' float diffuse = DiffuseColor*(0.5 * NdotL + 0.5); ');
  134. Add(' float specular = pow(NdotH, 64.0); ');
  135. Add(' vec4 FinalColour = AmbientColor*AmbientIntensity + ');
  136. Add(' DiffuseColor*diffuse*DiffuseIntensity + ');
  137. Add(' SpecularColor*specular*SpecularIntensity; ');
  138. Add(' gl_FragColor = FinalColour; //vec4( FinalColour, 1.0 ); ');
  139. Add('} ');
  140. end;
  141. FAmbientColor := TGLColor.Create(Self);
  142. //FDiffuseColor := TGLColor.Create(Self);
  143. FSpecularColor := TGLColor.Create(Self);
  144. //setup initial parameters
  145. FAmbientColor.SetColor(0.15, 0.15, 0.15, 1.0);
  146. //FDiffuseColor.SetColor(1, 1, 1, 1);
  147. FSpecularColor.SetColor(1.0, 1.0, 1.0, 1.0);
  148. FAmbientFactor := 0.8;
  149. FDiffuseFactor :=0.9;
  150. FSpecularFactor :=0.8;
  151. end;
  152. destructor TGLCustomGLSLSemShader.Destroy;
  153. begin
  154. FAmbientColor.Destroy;
  155. // FDiffuseColor.Destroy;
  156. FSpecularColor.Destroy;
  157. inherited;
  158. end;
  159. procedure TGLCustomGLSLSemShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
  160. begin
  161. GetGLSLProg.UseProgramObject;
  162. //Param['DiffuseColor'].AsVector4f := FDiffuseColor.Color;
  163. param['AmbientColor'].AsVector4f := FAmbientColor.Color;
  164. param['SpecularColor'].AsVector4f := FSpecularColor.Color;
  165. param['AmbientIntensity'].AsVector1f := FAmbientFactor;
  166. param['DiffuseIntensity'].AsVector1f := FDiffuseFactor;
  167. param['SpecularIntensity'].AsVector1f := FSpecularFactor;
  168. // Param['SpecPower'].AsVector1f := FSpecularPower;
  169. // Param['LightIntensity'].AsVector1f := FLightPower;
  170. Param['MainTexture'].AsTexture2D[0] := FMainTexture;
  171. end;
  172. function TGLCustomGLSLSemShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
  173. begin
  174. gl.ActiveTexture(GL_TEXTURE0_ARB);
  175. GetGLSLProg.EndUseProgramObject;
  176. Result := False;
  177. end;
  178. function TGLCustomGLSLSemShader.GetMaterialLibrary: TGLAbstractMaterialLibrary;
  179. begin
  180. Result := FMaterialLibrary;
  181. end;
  182. procedure TGLCustomGLSLSemShader.SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary);
  183. begin
  184. if FMaterialLibrary <> nil then FMaterialLibrary.RemoveFreeNotification(Self);
  185. FMaterialLibrary := Value;
  186. if (FMaterialLibrary <> nil)
  187. and (FMaterialLibrary is TGLAbstractMaterialLibrary) then
  188. FMaterialLibrary.FreeNotification(Self);
  189. end;
  190. procedure TGLCustomGLSLSemShader.SetMainTexTexture(const Value: TGLTexture);
  191. begin
  192. if FMainTexture = Value then Exit;
  193. FMainTexture := Value;
  194. NotifyChange(Self)
  195. end;
  196. function TGLCustomGLSLSemShader.GetMainTexName: TGLLibMaterialName;
  197. begin
  198. Result := TGLMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FMainTexture);
  199. if Result = '' then Result := FMainTexName;
  200. end;
  201. procedure TGLCustomGLSLSemShader.SetMainTexName(const Value: TGLLibMaterialName);
  202. begin
  203. // Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
  204. if FMainTexName = Value then Exit;
  205. FMainTexName := Value;
  206. FMainTexture := TGLMaterialLibrary(FMaterialLibrary).TextureByName(FMainTexName);
  207. NotifyChange(Self);
  208. end;
  209. //procedure TGLCustomGLSLSemShader.SetDiffuseColor(AValue: TGLColor);
  210. //begin
  211. // FDiffuseColor.DirectColor := AValue.Color;
  212. //end;
  213. procedure TGLCustomGLSLSemShader.SetAmbientColor(AValue: TGLColor);
  214. begin
  215. FAmbientColor.DirectColor := AValue.Color;
  216. end;
  217. procedure TGLCustomGLSLSemShader.SetSpecularColor(AValue: TGLColor);
  218. begin
  219. FSpecularColor.DirectColor := AValue.Color;
  220. end;
  221. procedure TGLCustomGLSLSemShader.Notification(AComponent: TComponent; Operation: TOperation);
  222. var
  223. Index: Integer;
  224. begin
  225. inherited;
  226. if Operation = opRemove then
  227. if AComponent = FMaterialLibrary then
  228. if FMaterialLibrary <> nil then
  229. begin
  230. if FMainTexture <> nil then
  231. begin
  232. Index := TGLMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FMainTexture);
  233. if Index <> -1 then
  234. SetMainTexTexture(nil);
  235. end;
  236. FMaterialLibrary := nil;
  237. end;
  238. end;
  239. end.