shader.monkey2 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. Namespace mojo.graphics
  2. Private
  3. Function BindUniforms( uniforms:Uniform[],params:ParamBuffer,filter:Bool )
  4. For Local u:=Eachin uniforms
  5. Local p:=params._params[u.id]
  6. Select u.type
  7. Case GL_FLOAT
  8. glUniform1f( u.location,p.scalar )
  9. Case GL_FLOAT_VEC4
  10. glUniform4fv( u.location,1,Varptr p.vector.x )
  11. Case GL_FLOAT_MAT4
  12. glUniformMatrix4fv( u.location,1,False,Varptr p.matrix.i.x )
  13. Case GL_SAMPLER_2D
  14. Local tex:=p.texture
  15. DebugAssert( tex,"Can't bind shader texture uniform '"+u.name+"' - no texture!" )
  16. glActiveTexture( GL_TEXTURE0+u.texunit )
  17. Local gltex:=tex.GLTexture
  18. If gltex
  19. glBindTexture( GL_TEXTURE_2D,tex.GLTexture )
  20. If (tex.Flags & TextureFlags.Filter) And filter
  21. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR )
  22. Else
  23. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST )
  24. Endif
  25. glUniform1i( u.location,u.texunit )
  26. Endif
  27. Default
  28. Assert( False,"Unsupported uniform type for param:"+u.name )
  29. End
  30. Next
  31. glActiveTexture( GL_TEXTURE0 )
  32. End
  33. Class Uniform
  34. Field name:String
  35. Field id:Int
  36. Field location:Int
  37. Field texunit:Int
  38. Field size:Int
  39. Field type:Int
  40. Method New( name:String,location:Int,texunit:Int,size:Int,type:Int )
  41. Self.name=name
  42. Self.id=ShaderParam.ParamId( Self.name )
  43. Self.texunit=texunit
  44. Self.location=location
  45. Self.size=size
  46. Self.type=type
  47. End
  48. End
  49. Class ShaderProgram
  50. Method New( sources:String[] )
  51. _sources=sources
  52. End
  53. Property Sources:String[]()
  54. Return _sources
  55. End
  56. Property EnvUniforms:Uniform[]()
  57. Return _envUniforms
  58. End
  59. Property Uniforms:Uniform[]()
  60. Return _uniforms
  61. End
  62. Property GLProgram:GLuint()
  63. If _seq=glGraphicsSeq
  64. Return _glProgram
  65. Endif
  66. BuildProgram()
  67. EnumUniforms()
  68. _seq=glGraphicsSeq
  69. Return _glProgram
  70. End
  71. Private
  72. Field _sources:String[]
  73. Field _seq:Int
  74. Field _glProgram:GLuint
  75. Field _envUniforms:Uniform[]
  76. Field _uniforms:Uniform[]
  77. Method BuildProgram()
  78. Local csource:=""
  79. Local vsource:=""
  80. Local fsource:=""
  81. For Local source:=Eachin _sources
  82. Local i0:=source.Find( "//@vertex" )
  83. If i0=-1
  84. Print "Shader source:~n"+source
  85. Assert( False,"Can't find //@vertex chunk" )
  86. Endif
  87. Local i1:=source.Find( "//@fragment" )
  88. If i1=-1
  89. Print "Shader source:~n"+source
  90. Assert( False,"Can't find //@fragment chunk" )
  91. Endif
  92. csource+=source.Slice( 0,i0 )+"~n"
  93. vsource+=source.Slice( i0,i1 )+"~n"
  94. fsource+=source.Slice( i1 )+"~n"
  95. Next
  96. vsource=csource+vsource
  97. fsource=csource+fsource
  98. Local vshader:=glCompile( GL_VERTEX_SHADER,vsource )
  99. Local fshader:=glCompile( GL_FRAGMENT_SHADER,fsource )
  100. _glProgram=glCreateProgram()
  101. glAttachShader( _glProgram,vshader )
  102. glAttachShader( _glProgram,fshader )
  103. ' glDeleteShader( vshader )
  104. ' glDeleteShader( fshader )
  105. glBindAttribLocation( _glProgram,0,"mx2_VertexPosition" )
  106. glBindAttribLocation( _glProgram,1,"mx2_VertexTexCoord0" )
  107. glBindAttribLocation( _glProgram,2,"mx2_VertexTangent" )
  108. glBindAttribLocation( _glProgram,3,"mx2_VertexColor" )
  109. glLink( _glProgram )
  110. End
  111. Method EnumUniforms()
  112. Local envUniforms:=New Stack<Uniform>
  113. Local uniforms:=New Stack<Uniform>
  114. Local n:Int
  115. glGetProgramiv( _glProgram,GL_ACTIVE_UNIFORMS,Varptr n )
  116. Local size:Int,type:UInt,length:Int,nameBuf:=New Byte[256],texunit:=0
  117. For Local i:=0 Until n
  118. glGetActiveUniform( _glProgram,i,nameBuf.Length,Varptr length,Varptr size,Varptr type,Cast<GLchar Ptr>( nameBuf.Data ) )
  119. Local name:=String.FromCString( nameBuf.Data )
  120. Local location:=glGetUniformLocation( _glProgram,name )
  121. If location=-1 Continue 'IE fix...
  122. Local u:=New Uniform( name,location,texunit,size,type )
  123. If name.StartsWith( "mx2_" )
  124. envUniforms.Push( u )
  125. Else
  126. uniforms.Push( u )
  127. Endif
  128. Select type
  129. Case GL_SAMPLER_2D
  130. texunit+=1
  131. End
  132. Next
  133. _envUniforms=envUniforms.ToArray()
  134. _uniforms=uniforms.ToArray()
  135. End
  136. End
  137. Public
  138. #rem monkeydoc @hidden
  139. #end
  140. Struct ShaderParam
  141. Field scalar:Float
  142. Field vector:Vec4f
  143. Field matrix:Mat4f
  144. Field texture:Texture
  145. Function ParamId:Int( name:String )
  146. Local id:=_ids[name]
  147. If id Return id
  148. _nextId+=1
  149. _ids[name]=_nextId
  150. ' Print "Shader param "+name+"="+_nextId
  151. Return _nextId
  152. End
  153. Private
  154. Global _nextId:Int
  155. Global _ids:=New StringMap<Int>
  156. End
  157. #rem monkeydoc @hidden
  158. #end
  159. Class ShaderEnv
  160. Method New( sourceCode:String )
  161. _source=sourceCode
  162. _id=_nextId
  163. _nextId+=1
  164. End
  165. Property SourceCode:String()
  166. Return _source
  167. End
  168. Property Id:Int()
  169. Return _id
  170. End
  171. Private
  172. Field _source:String
  173. Field _id:Int
  174. Global _nextId:=0
  175. End
  176. #rem monkeydoc @hidden
  177. #end
  178. Class ParamBuffer
  179. Method SetVector( name:String,value:Vec4f )
  180. _params[ ShaderParam.ParamId( name ) ].vector=value
  181. End
  182. Method SetMatrix( name:String,value:Mat4f )
  183. _params[ ShaderParam.ParamId( name ) ].matrix=value
  184. End
  185. Method SetTexture( name:String,value:Texture )
  186. _params[ ShaderParam.ParamId( name ) ].texture=value
  187. End
  188. Method SetColor( name:String,value:Color )
  189. _params[ ShaderParam.ParamId( name ) ].vector=New Vec4f( value.r,value.g,value.b,value.a )
  190. End
  191. Private
  192. Field _params:=New ShaderParam[32]
  193. End
  194. #rem monkeydoc @hidden
  195. #end
  196. Class Shader
  197. Method New( sourceCode:String )
  198. _source=sourceCode
  199. End
  200. Property SourceCode:String()
  201. Return _source
  202. End
  203. #rem monkeydoc @hidden
  204. #end
  205. Method Bind( env:ShaderEnv )
  206. If _seq<>glGraphicsSeq
  207. _seq=glGraphicsSeq
  208. _bound=Null
  209. Endif
  210. Local p:=_programs[env.Id]
  211. If Not p
  212. p=New ShaderProgram( New String[]( env._source,_source ) )
  213. _programs[env.Id]=p
  214. Endif
  215. If _bound=p Return
  216. glUseProgram( p.GLProgram )
  217. _bound=p
  218. End
  219. #rem monkeydoc @hidden
  220. #end
  221. Method BindEnvParams( params:ParamBuffer )
  222. BindUniforms( _bound._envUniforms,params,True )
  223. End
  224. #rem monkeydoc @hidden
  225. #end
  226. Method BindParams( params:ParamBuffer,filter:Bool )
  227. BindUniforms( _bound._uniforms,params,filter )
  228. End
  229. #rem monkeydoc @hidden
  230. #end
  231. Function GetShader:Shader( name:String )
  232. If Not _shaders
  233. _shaders=New StringMap<Shader>
  234. _shaders["sprite"]=New Shader( stringio.LoadString( "asset::mojo/shader_sprite.glsl" ) )
  235. _shaders["phong"]=New Shader( stringio.LoadString( "asset::mojo/shader_phong.glsl" ) )
  236. _shaders["font"]=New Shader( stringio.LoadString( "asset::mojo/shader_font.glsl" ) )
  237. _shaders["null"]=New Shader( stringio.LoadString( "asset::mojo/shader_null.glsl" ) )
  238. Endif
  239. Return _shaders[name]
  240. End
  241. Private
  242. Field _source:String
  243. Field _programs:=New ShaderProgram[16]
  244. Global _seq:Int
  245. Global _bound:ShaderProgram
  246. Global _shaders:StringMap<Shader>
  247. End