Shader.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /*
  2. * Copyright (c) 2009-2010 jMonkeyEngine
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package com.jme3.shader;
  33. import com.jme3.renderer.Renderer;
  34. import com.jme3.scene.VertexBuffer;
  35. import com.jme3.util.IntMap;
  36. import com.jme3.util.IntMap.Entry;
  37. import com.jme3.util.ListMap;
  38. import com.jme3.util.NativeObject;
  39. import java.util.ArrayList;
  40. import java.util.Collection;
  41. public final class Shader extends NativeObject {
  42. /**
  43. *
  44. * @deprecated shader language now specified per shader source. See
  45. * {@link ShaderSource#setLanguage(String)
  46. */
  47. @Deprecated
  48. private String language;
  49. /**
  50. * A list of all shader sources currently attached.
  51. */
  52. private ArrayList<ShaderSource> shaderSourceList;
  53. /**
  54. * Maps uniform name to the uniform variable.
  55. */
  56. private ListMap<String, Uniform> uniforms;
  57. /**
  58. * Maps attribute name to the location of the attribute in the shader.
  59. */
  60. private IntMap<Attribute> attribs;
  61. /**
  62. * Type of shader. The shader will control the pipeline of it's type.
  63. */
  64. public static enum ShaderType {
  65. /**
  66. * Control fragment rasterization. (e.g color of pixel).
  67. */
  68. Fragment,
  69. /**
  70. * Control vertex processing. (e.g transform of model to clip space)
  71. */
  72. Vertex,
  73. /**
  74. * Control geometry assembly. (e.g compile a triangle list from input data)
  75. */
  76. Geometry;
  77. }
  78. /**
  79. * Shader source describes a shader object in OpenGL. Each shader source
  80. * is assigned a certain pipeline which it controls (described by it's type).
  81. */
  82. public static class ShaderSource extends NativeObject {
  83. ShaderType sourceType;
  84. String language;
  85. String name;
  86. String source;
  87. String defines;
  88. public ShaderSource(ShaderType type){
  89. super(ShaderSource.class);
  90. this.sourceType = type;
  91. if (type == null) {
  92. throw new NullPointerException("The shader type must be specified");
  93. }
  94. }
  95. protected ShaderSource(ShaderSource ss){
  96. super(ShaderSource.class, ss.id);
  97. // No data needs to be copied.
  98. // (This is a destructable clone)
  99. }
  100. public ShaderSource(){
  101. super(ShaderSource.class);
  102. }
  103. public void setName(String name){
  104. this.name = name;
  105. }
  106. public String getName(){
  107. return name;
  108. }
  109. public ShaderType getType() {
  110. return sourceType;
  111. }
  112. public String getLanguage() {
  113. return language;
  114. }
  115. public void setLanguage(String language) {
  116. if (language == null) {
  117. throw new NullPointerException("Shader language cannot be null");
  118. }
  119. this.language = language;
  120. setUpdateNeeded();
  121. }
  122. public void setSource(String source){
  123. if (source == null) {
  124. throw new NullPointerException("Shader source cannot be null");
  125. }
  126. this.source = source;
  127. setUpdateNeeded();
  128. }
  129. public void setDefines(String defines){
  130. if (defines == null) {
  131. throw new NullPointerException("Shader defines cannot be null");
  132. }
  133. this.defines = defines;
  134. setUpdateNeeded();
  135. }
  136. public String getSource(){
  137. return source;
  138. }
  139. public String getDefines(){
  140. return defines;
  141. }
  142. @Override
  143. public String toString(){
  144. String nameTxt = "";
  145. if (name != null)
  146. nameTxt = "name="+name+", ";
  147. if (defines != null)
  148. nameTxt += "defines, ";
  149. return getClass().getSimpleName() + "["+nameTxt+"type="
  150. + sourceType.name()+", language=" + language + "]";
  151. }
  152. public void resetObject(){
  153. id = -1;
  154. setUpdateNeeded();
  155. }
  156. public void deleteObject(Object rendererObject){
  157. ((Renderer)rendererObject).deleteShaderSource(ShaderSource.this);
  158. }
  159. public NativeObject createDestructableClone(){
  160. return new ShaderSource(ShaderSource.this);
  161. }
  162. }
  163. /**
  164. * @deprecated Shader sources are now associated with the shader
  165. * language.
  166. */
  167. @Deprecated
  168. public Shader(String language){
  169. super(Shader.class);
  170. this.language = language;
  171. initialize();
  172. }
  173. /**
  174. * Initializes the shader for use, must be called after the
  175. * constructor without arguments is used.
  176. */
  177. public void initialize() {
  178. shaderSourceList = new ArrayList<ShaderSource>();
  179. uniforms = new ListMap<String, Uniform>();
  180. attribs = new IntMap<Attribute>();
  181. }
  182. /**
  183. * Creates a new shader, {@link #initialize() } must be called
  184. * after this constructor for the shader to be usable.
  185. */
  186. public Shader(){
  187. super(Shader.class);
  188. }
  189. /**
  190. * Do not use this constructor. Used for destructable clones only.
  191. */
  192. protected Shader(Shader s){
  193. super(Shader.class, s.id);
  194. // Shader sources cannot be shared, therefore they must
  195. // be destroyed together with the parent shader.
  196. shaderSourceList = new ArrayList<ShaderSource>();
  197. for (ShaderSource source : s.shaderSourceList){
  198. shaderSourceList.add( (ShaderSource)source.createDestructableClone() );
  199. }
  200. }
  201. /**
  202. * @deprecated Use the method that takes a language argument instead.
  203. * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) }
  204. */
  205. @Deprecated
  206. public void addSource(ShaderType type, String name, String source, String defines) {
  207. addSource(type, name, source, defines, this.language);
  208. }
  209. /**
  210. * @deprecated Use the method that takes a language argument instead.
  211. * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) }
  212. */
  213. @Deprecated
  214. public void addSource(ShaderType type, String source, String defines){
  215. addSource(type, null, source, defines);
  216. }
  217. /**
  218. * @deprecated Use the method that takes a language argument instead.
  219. * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) }
  220. */
  221. @Deprecated
  222. public void addSource(ShaderType type, String source){
  223. addSource(type, source, null);
  224. }
  225. /**
  226. * @deprecated Shader sources may not be shared.
  227. * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) }
  228. */
  229. @Deprecated
  230. private void addSource(ShaderSource source){
  231. shaderSourceList.add(source);
  232. setUpdateNeeded();
  233. }
  234. /**
  235. * Adds source code to a certain pipeline.
  236. *
  237. * @param type The pipeline to control
  238. * @param source The shader source code (in GLSL).
  239. * @param defines Preprocessor defines (placed at the beginning of the shader)
  240. * @param language The shader source language, currently accepted is GLSL###
  241. * where ### is the version, e.g. GLSL100 = GLSL 1.0, GLSL330 = GLSL 3.3, etc.
  242. */
  243. public void addSource(ShaderType type, String name, String source, String defines, String language){
  244. ShaderSource shaderSource = new ShaderSource(type);
  245. shaderSource.setSource(source);
  246. shaderSource.setName(name);
  247. shaderSource.setLanguage(language);
  248. if (defines != null) {
  249. shaderSource.setDefines(defines);
  250. }
  251. shaderSourceList.add(shaderSource);
  252. setUpdateNeeded();
  253. }
  254. public Uniform getUniform(String name){
  255. Uniform uniform = uniforms.get(name);
  256. if (uniform == null){
  257. uniform = new Uniform();
  258. uniform.name = name;
  259. uniforms.put(name, uniform);
  260. }
  261. return uniform;
  262. }
  263. public void removeUniform(String name){
  264. uniforms.remove(name);
  265. }
  266. public Attribute getAttribute(VertexBuffer.Type attribType){
  267. int ordinal = attribType.ordinal();
  268. Attribute attrib = attribs.get(ordinal);
  269. if (attrib == null){
  270. attrib = new Attribute();
  271. attrib.name = attribType.name();
  272. attribs.put(ordinal, attrib);
  273. }
  274. return attrib;
  275. }
  276. public ListMap<String, Uniform> getUniformMap(){
  277. return uniforms;
  278. }
  279. public Collection<ShaderSource> getSources(){
  280. return shaderSourceList;
  281. }
  282. /**
  283. * @deprecated Shaders no longer have a language variable,
  284. * use {@link ShaderSource#getLanguage() } instead.
  285. */
  286. @Deprecated
  287. public String getLanguage(){
  288. return language;
  289. }
  290. @Override
  291. public String toString() {
  292. return getClass().getSimpleName() +
  293. "[numSources=" + shaderSourceList.size() +
  294. ", numUniforms=" + uniforms.size() +
  295. ", shaderSources=" + getSources() + "]";
  296. }
  297. /**
  298. * @deprecated This method is not needed since deleting
  299. * a shader causes the sources to delete as well, thus its not required
  300. * for them to be GC'd to be removed from GL.
  301. */
  302. @Deprecated
  303. public void resetSources(){
  304. shaderSourceList.clear();
  305. }
  306. /**
  307. * @deprecated Unusable shaders cause the renderer to crash,
  308. * therefore this field no longer serves any purpose.
  309. */
  310. @Deprecated
  311. public boolean isUsable(){
  312. return true;
  313. }
  314. /**
  315. * @deprecated Unusable shaders cause the renderer to crash,
  316. * therefore this field no longer serves any purpose.
  317. */
  318. @Deprecated
  319. public void setUsable(boolean usable){
  320. }
  321. /**
  322. * Usually called when the shader itself changes or during any
  323. * time when the variable locations need to be refreshed.
  324. */
  325. public void resetLocations() {
  326. if (uniforms != null) {
  327. // NOTE: Shader sources will be reset seperately from the shader itself.
  328. for (Uniform uniform : uniforms.values()) {
  329. uniform.reset(); // fixes issue with re-initialization
  330. }
  331. }
  332. if (attribs != null) {
  333. for (Entry<Attribute> entry : attribs) {
  334. entry.getValue().location = ShaderVariable.LOC_UNKNOWN;
  335. }
  336. }
  337. }
  338. @Override
  339. public void setUpdateNeeded(){
  340. super.setUpdateNeeded();
  341. resetLocations();
  342. }
  343. /**
  344. * Called by the object manager to reset all object IDs. This causes
  345. * the shader to be reuploaded to the GPU incase the display was restarted.
  346. */
  347. @Override
  348. public void resetObject() {
  349. this.id = -1;
  350. for (ShaderSource source : shaderSourceList){
  351. source.resetObject();
  352. }
  353. setUpdateNeeded();
  354. }
  355. @Override
  356. public void deleteObject(Object rendererObject) {
  357. ((Renderer)rendererObject).deleteShader(this);
  358. }
  359. public NativeObject createDestructableClone(){
  360. return new Shader(this);
  361. }
  362. }