Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Robert Osfield et. al., On 14.1.2016 16:34, Robert Osfield wrote: I'm still open to making the shader parsing extensible, it seems like an interesting experimental tool. As Sebastian already pointed out, the actual parsing can be done outside osg, perhaps before Shader::setShaderSource() call or at some already provided callback. In my opinion, it is more interesting to have a spot where all the necessary information for the preprocessing step converge, so that at this point user can regain some useful control over the shader composition. I was going through a Shader.cpp to find a spot/function where all the information needed for the shader composition is at hand. Unsurprisingly, that function turned out to be void PerContextShader::compileShader(osg::State& state);. The PerContextShader::compileShader() does all the preprocessing on a shader source, like state.convertVertexShaderSourceToOsgBuiltIns(), insertion of the #version, inserting line numbers for debug purposes and generates the define string based on current define set found in osg::State. The PerContextShader::compileShader() is a function of an internal class but the osg::Shader::compileShader(osg::State& state) (which calls PerContextShader::compileShader()) isn't. That being said, minimum work required to provide some degree of extensibility is to simply make osg::Shader::compileShader(osg::State& state) virtual. Thoughts? Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Nick, On 14.1.2016 15:31, Trajce Nikolov NICK wrote: Hi Robert M. I went through this thread fast and I see you are trying (at least your show case) is lighting and use of shader composition. The approach you are taking is what I was using too, some years ago. But there are other methods that does not require any mods and will work just fine with the existing shader composition features. You can for example encode all the light attributes into a texture buffer object (think of this as an image where each float texel is one light attribute like color, etc). Frankly, I never thought about multi-light problem this way. I wonder if such technique can be generalized enough, e.g. hidden behind the scenes, so the user of the lighting framework doesn't have to deal with the texture objects. My guess is yes, but of course, I should look into technical merits of the implementation first. Have a look at this, it is Forward+ implementation in opensource project https://www.youtube.com/watch?v=beSkETJ_vgY impressive! We are releasing a new version with F+ lighting available these days, so you might want to keep an eye on it. Looking forward. Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Sebastian, Hi Robert, Hi Sebastian , First of all, the lightning shader only illustrates one of the cases where (optionally) repeating a code block containing substitution parameter can be useful. I used the multi-light lightning as an illustration only. First, thank you for your input. Yes, that is more or less the same approach I'm currently using. The downside of this approach is that it requires additional nontrivial code logic for the uniform array management (u_LightColor) and that is why I started to look at the alternatives. What could be more complicated there than to setup individual uniforms? Sorry this doesn't pass as a valid argument. If you have to hold the number of used lights somewhere you can hold a reference to the uniform as well. Sorry, but that is not what I had in mind. The problem here is the management of the array uniform's content and not the reference to it or the light count etc. Let say I only want to disable one of the lights, say LIGHT0 eg. stateset->setDefines("LIGHT0", osg::StateAttribute::OFF). What will you do? Let's say you have a fixed maximum on N, than you create a UBO/Array of this size and provide a count-uniform for the maximum valid entries. If a light gets disabled, you simply remove it, copy it to the back and set your count to N-1. In the shader you simply loop from 0 to count instead of N. That might break compiler optimization, but it won't hurt too much I guess. When using the setDefine, OSG will have to issue a recompile of this new variant, which will degrade performance if all combinations are needed. Assume 16 Lightsource, that will produce 65536 possible shader programs ... and that is only 16, not 500, or 1000 ... Having 1024 individually switchable Lightsources would totally wreck your idea of having an alternative to my solution. 2^1024 might exceed the numbers of atoms in the known universe, so there is not a remote chance to solve this with shader combinations... The question was purely rhetorical. I just wanted to prove my point regarding the uniform's content management vs already provided setDefines("LIGHT0", osg::StateAttribute::OFF). I didn't expect all that. Sorry for the fuzz :) BTW, I'm not planing to toggle all possible on/off combinations just to see all the permutations, the normal graph usage is what I'm after. Normal graph usage might exactly trigger a lot of combinations. My point is not that theoretical if you take into account that basically everyone could have used the feature if it was part of the core, thus the example is a practical one :-) I didn't want to prove anything here, I simply wanted to point out some practical problems. I know and I'm grateful for that. Anyway, based on feedback, I already ditched the idea and I'm now looking into alternative possibilities, mainly if shader composition can be extended in a nonintrusive way. Exactly, that was my intention, to add a higher degree of complexity and hopefully solve some problems that "turing-complete" language can't. Turing complete solves all computable problems ;-) I do understand your motivation, but I still don't see the gain really. I've presented some alternative ways to solve your problem, as I came across some of those challenges too. The idea Robert mentioned might be a good one, basically we could use some kind of callback to let the user-code preprocess the shader, wait actually we can already do this, when it is loaded via a LoadCallback :-) Actually I'm preprocessing my shader code when it's loaded to perform "include" and automated shader-define setup, so this might work for your "loop" too. That would defeat the purpose of the #pragma(tic) shader composition. You may then as well pre-parse #pragma import_defines and #pragma requires and pre-generate all the shader permutations. The purpose of #pragma(tic) shader composition is shader generation based on current define set (see the osg::State). Yes and? I'm parsing include hierarchies and therefore need to add the defines found there to the #pragma import_defines. The bulk work done by the osg::State is to determine if a new program needs to be compiled based on the set of defines. My composition is purely to keep the shader code maintainable and reusable. Currently some of the "Ubershaders" have 20-30 defines, which seriously don't want to write in the the import_defines by hand. Again I simply wanted to point out some possibilities to get you your loop-mechanism. I see. Thank you for that, too. Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
> Frankly, I never thought about multi-light problem this way. I wonder if such technique can be generalized enough, e.g. hidden behind the scenes, so the user of the lighting framework doesn't have to deal with the texture objects That is what I though when designing OpenIG. Since I sounded like placing a commercial in this thread (which I actually did, but this is OSG project) I will not spend too much on details here, but yes, the light implementation is hidden from the "scene", the interface. It has plugin-based approach and the lighting implementation is completely implemented in a way (simple or complex) again hidden. For example in the current repo you can find simple lights implementation very similar to what you are doing. Then this plugin in the upcoming release is replaced by F+ implementation, without changing the interface. So it will not break any code, it is simple replacing a plugin dll in a xml config file. Ping me privately or join the OpenIG forum if you want to give it a shot. I can help you set up And thanks, Nick On Fri, Jan 15, 2016 at 9:43 AM, Robert Milharcic < robert.milhar...@ib-caddy.si> wrote: > Hi Nick, > > On 14.1.2016 15:31, Trajce Nikolov NICK wrote: > >> Hi Robert M. >> >> I went through this thread fast and I see you are trying (at least your >> show case) is lighting and use of shader composition. The approach you are >> taking is what I was using too, some years ago. But there are other >> methods >> that does not require any mods and will work just fine with the existing >> shader composition features. You can for example encode all the light >> attributes into a texture buffer object (think of this as an image where >> each float texel is one light attribute like color, etc). >> > > Frankly, I never thought about multi-light problem this way. I wonder if > such technique can be generalized enough, e.g. hidden behind the scenes, so > the user of the lighting framework doesn't have to deal with the texture > objects. My guess is yes, but of course, I should look into technical > merits of the implementation first. > > Have a look at this, it is Forward+ implementation in opensource project >> https://www.youtube.com/watch?v=beSkETJ_vgY >> > impressive! > > We are releasing a new version with F+ lighting available these days, so >> you might want to keep an eye on it. >> > > Looking forward. > > Cheers, > Robert Milharcic > > ___ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > -- trajce nikolov nick ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Robert, Hi Sebastian , First of all, the lightning shader only illustrates one of the cases where (optionally) repeating a code block containing substitution parameter can be useful. I used the multi-light lightning as an illustration only. First, thank you for your input. Yes, that is more or less the same approach I'm currently using. The downside of this approach is that it requires additional nontrivial code logic for the uniform array management (u_LightColor) and that is why I started to look at the alternatives. What could be more complicated there than to setup individual uniforms? Sorry this doesn't pass as a valid argument. If you have to hold the number of used lights somewhere you can hold a reference to the uniform as well. Sorry, but that is not what I had in mind. The problem here is the management of the array uniform's content and not the reference to it or the light count etc. Let say I only want to disable one of the lights, say LIGHT0 eg. stateset->setDefines("LIGHT0", osg::StateAttribute::OFF). What will you do? Let's say you have a fixed maximum on N, than you create a UBO/Array of this size and provide a count-uniform for the maximum valid entries. If a light gets disabled, you simply remove it, copy it to the back and set your count to N-1. In the shader you simply loop from 0 to count instead of N. That might break compiler optimization, but it won't hurt too much I guess. When using the setDefine, OSG will have to issue a recompile of this new variant, which will degrade performance if all combinations are needed. Assume 16 Lightsource, that will produce 65536 possible shader programs ... and that is only 16, not 500, or 1000 ... Having 1024 individually switchable Lightsources would totally wreck your idea of having an alternative to my solution. 2^1024 might exceed the numbers of atoms in the known universe, so there is not a remote chance to solve this with shader combinations... The question was purely rhetorical. I just wanted to prove my point regarding the uniform's content management vs already provided setDefines("LIGHT0", osg::StateAttribute::OFF). I didn't expect all that. Sorry for the fuzz :) BTW, I'm not planing to toggle all possible on/off combinations just to see all the permutations, the normal graph usage is what I'm after. Normal graph usage might exactly trigger a lot of combinations. My point is not that theoretical if you take into account that basically everyone could have used the feature if it was part of the core, thus the example is a practical one :-) I didn't want to prove anything here, I simply wanted to point out some practical problems. Exactly, that was my intention, to add a higher degree of complexity and hopefully solve some problems that "turing-complete" language can't. Turing complete solves all computable problems ;-) I do understand your motivation, but I still don't see the gain really. I've presented some alternative ways to solve your problem, as I came across some of those challenges too. The idea Robert mentioned might be a good one, basically we could use some kind of callback to let the user-code preprocess the shader, wait actually we can already do this, when it is loaded via a LoadCallback :-) Actually I'm preprocessing my shader code when it's loaded to perform "include" and automated shader-define setup, so this might work for your "loop" too. That would defeat the purpose of the #pragma(tic) shader composition. You may then as well pre-parse #pragma import_defines and #pragma requires and pre-generate all the shader permutations. The purpose of #pragma(tic) shader composition is shader generation based on current define set (see the osg::State). Yes and? I'm parsing include hierarchies and therefore need to add the defines found there to the #pragma import_defines. The bulk work done by the osg::State is to determine if a new program needs to be compiled based on the set of defines. My composition is purely to keep the shader code maintainable and reusable. Currently some of the "Ubershaders" have 20-30 defines, which seriously don't want to write in the the import_defines by hand. Again I simply wanted to point out some possibilities to get you your loop-mechanism. Cheers Sebastian Cheers Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
On 14 January 2016 at 14:56, Robert Milharcicwrote: > If I'm not mistaken, the #pragma directive is used by the C/C++ preprocessor > for providing additional information, beyond what the language itself can > offer. I thought this was the main inspiration for #pragma(tic) shader > composition. Anyway, based on feedback I'm now convinced that my proposition > isn't that useful as I thought :) and on that note, I rest my case. #pragma is indeed the C/C++ mechanism for providing extra hints to specific compilers. In terms of coming up with #pragma(tic) shader composition I started with the observation that C/C++ macro's and #define's that could do much of the job of shader composition, but then I needed a mechanism for the shader to specify which #define's it required as input to the shaders. After a bit of head scratching it occurred to me that #pragma was support by GLSL and since it's a language feature I could piggy back the extra information specification into the shaders. Once I spotted this missing bit of jigsaw it was just too elegant not to work, thankfully the implementation ended up being relatively tidy too. I'm still open to making the shader parsing extensible, it seems like an interesting experimental tool. Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
[osg-users] Pragmatic shader - a new #pragma directive proposition
Hi all, With the pragmatic shader one could implement multiple lights and other repetitive constructs like this: -- start of shader code -- #pragma import_defines ( LIGHTING, LIGHT0, LIGHT1 ) #ifdef LIGHTING #ifdef LIGHT0 uniform vec4 u_LightColor0; #endif #ifdef LIGHT1 uniform vec4 u_LightColor1; #endif varying vec4 basecolor; void light( in vec4 lightColor, inout vec4 color ); #endif void main(void) { basecolor = gl_Color; #ifdef LIGHTING #ifdef LIGHT0 light( u_LightColor0, basecolor); #endif #ifdef LIGHT1 light( u_LightColor1, basecolor); #endif #endif gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } -- end of shader code -- ... and to enable both lights: stateset->setDefine("LIGHTING"); stateset->setDefine("LIGHT0"); stateset->setDefine("LIGHT1"); The problem with this approach is that nobody really knows in advance how many more lights will be needed. Moreover, the shader can get heavily bloated when more and more lights are added. As a solution I would like to propose a new #pragma construct: #pragma repeat_begin( DEFINE_IDENTIFIER${SubstitutionParameter} ) (shader code block) #pragma repeat_end() ... and the shader code supporting arbitrary number of lights would then look like this: -- start of shader code -- #pragma import_defines ( LIGHTING, LIGHT${Member} ) #ifdef LIGHTING #pragma repeat_begin( LIGHT${Member} ) uniform vec4 u_LightColor${Member}; #pragma repeat_end() varying vec4 basecolor; void light( in vec4 lightColor, inout vec4 color ); #endif void main(void) { basecolor = gl_Color; #ifdef LIGHTING #pragma repeat_begin( LIGHT${Member} ) light( u_LightColor${Member}, basecolor); #pragma repeat_end() #endif gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } -- end of shader code -- ... where ${Member} is a substitution parameter and LIGHT is define identifier. Then with: stateset->setDefine("LIGHTING"); stateset->setDefine("LIGHT${0}"); stateset->setDefine("LIGHT${1}"); stateset->setDefine("LIGHT${5}"); ... where ${0}, ${1}, ${5} are substitution values, osg would produce following shader code: -- start of shader code -- #define LIGHTING #define LIGHT0 #define LIGHT1 #define LIGHT5 #ifdef LIGHTING uniform vec4 u_LightColor0; uniform vec4 u_LightColor1; uniform vec4 u_LightColor5; varying vec4 basecolor; void light( in vec4 lightColor, inout vec4 color ); #endif void main(void) { basecolor = gl_Color; #ifdef LIGHTING light( u_LightColor0, basecolor); light( u_LightColor1, basecolor); light( u_LightColor5, basecolor); #endif gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } -- end of shader code -- Before I do any coding I'd like to know if proposed solution would be of any use to the osg community? Or maybe there is a better way? I'm currently solving these kinds of problems with uniform arrays, but unfortunately, the uniform array has its own max number of elements and the management code of such approach tend to be complicated... Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Robert, This seems more complicated than needed. Why not pass the number of lights as a compile time constant #pragma import_defines (NUM_LIGHTS) shader_state->setDefine("NUM_LIGHTS",12); and use uniform arrays: uniform vec4 u_LightColor[NUM_LIGHTS]; for (int i = 0; i < NUM_LIGHTS;++i) { light+=calcLight(u_LightColor[i], ...): } I feel your approach will bloat the preprocessor code path and will complicate the use. Hi all, With the pragmatic shader one could implement multiple lights and other repetitive constructs like this: -- start of shader code -- #pragma import_defines ( LIGHTING, LIGHT0, LIGHT1 ) #ifdef LIGHTING #ifdef LIGHT0 uniform vec4 u_LightColor0; #endif #ifdef LIGHT1 uniform vec4 u_LightColor1; #endif varying vec4 basecolor; void light( in vec4 lightColor, inout vec4 color ); #endif void main(void) { basecolor = gl_Color; #ifdef LIGHTING #ifdef LIGHT0 light( u_LightColor0, basecolor); #endif #ifdef LIGHT1 light( u_LightColor1, basecolor); #endif #endif gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } -- end of shader code -- ... and to enable both lights: stateset->setDefine("LIGHTING"); stateset->setDefine("LIGHT0"); stateset->setDefine("LIGHT1"); The problem with this approach is that nobody really knows in advance how many more lights will be needed. Moreover, the shader can get heavily bloated when more and more lights are added. As a solution I would like to propose a new #pragma construct: #pragma repeat_begin( DEFINE_IDENTIFIER${SubstitutionParameter} ) (shader code block) #pragma repeat_end() ... and the shader code supporting arbitrary number of lights would then look like this: -- start of shader code -- #pragma import_defines ( LIGHTING, LIGHT${Member} ) #ifdef LIGHTING #pragma repeat_begin( LIGHT${Member} ) uniform vec4 u_LightColor${Member}; #pragma repeat_end() varying vec4 basecolor; void light( in vec4 lightColor, inout vec4 color ); #endif void main(void) { basecolor = gl_Color; #ifdef LIGHTING #pragma repeat_begin( LIGHT${Member} ) light( u_LightColor${Member}, basecolor); #pragma repeat_end() #endif gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } -- end of shader code -- ... where ${Member} is a substitution parameter and LIGHT is define identifier. Then with: stateset->setDefine("LIGHTING"); stateset->setDefine("LIGHT${0}"); stateset->setDefine("LIGHT${1}"); stateset->setDefine("LIGHT${5}"); ... where ${0}, ${1}, ${5} are substitution values, osg would produce following shader code: -- start of shader code -- #define LIGHTING #define LIGHT0 #define LIGHT1 #define LIGHT5 #ifdef LIGHTING uniform vec4 u_LightColor0; uniform vec4 u_LightColor1; uniform vec4 u_LightColor5; varying vec4 basecolor; void light( in vec4 lightColor, inout vec4 color ); #endif void main(void) { basecolor = gl_Color; #ifdef LIGHTING light( u_LightColor0, basecolor); light( u_LightColor1, basecolor); light( u_LightColor5, basecolor); #endif gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } -- end of shader code -- Before I do any coding I'd like to know if proposed solution would be of any use to the osg community? Or maybe there is a better way? I'm currently solving these kinds of problems with uniform arrays, but unfortunately, the uniform array has its own max number of elements and the management code of such approach tend to be complicated... Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Robert M, et. al, I understand the motivation the proposal but it does look like it'll complicate the parsing significantly so am inclined to suggest we look at the problem at look for easier ways to implement it. In terms of code bloat in shaders, the #pragma(tic) shader composition ensures that the final code passed the OpenGL will have all the unimplemented paths removed so performance won't be an issue. For developers code bloat in shaders is an potential issue, one thing you do to help would be to wrap up all the lighting calls into a small set of functions that are called from the main, these functions are implemented in separate shaders that handle all the different code paths so at least the complexity is kept in one place and can be reused easily. A second possibility would be to have developers auto generate shaders so avoid creating bloated shaders directly. A third approach might be to have the ability to provide a custom parser to the OSG so that it can handle custom syntax that developers feel suits their needs better than the default set of features provided by the core #pragma(tic) shader composition. Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
On 14.1.2016 9:52, Sebastian Messerschmidt wrote: Hi Robert, This seems more complicated than needed. Why not pass the number of lights as a compile time constant #pragma import_defines (NUM_LIGHTS) shader_state->setDefine("NUM_LIGHTS",12); and use uniform arrays: uniform vec4 u_LightColor[NUM_LIGHTS]; for (int i = 0; i < NUM_LIGHTS;++i) { light+=calcLight(u_LightColor[i], ...): } I feel your approach will bloat the preprocessor code path and will complicate the use. Hi Sebastian, First, thank you for your input. Yes, that is more or less the same approach I'm currently using. The downside of this approach is that it requires additional nontrivial code logic for the uniform array management (u_LightColor) and that is why I started to look at the alternatives. There is also an upper limit for the size of the array that needs to be taken into account. Also, the loop represents unnecessary overhead (though, this is not a problem on a never hardware). On the other hand, my suggestion fits well into existing pragmatic shader composition logic and probably has less downsides. Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Robert Osfield, On 14.1.2016 10:10, Robert Osfield wrote: Hi Robert M, et. al, I understand the motivation the proposal but it does look like it'll complicate the parsing significantly so am inclined to suggest we look at the problem at look for easier ways to implement it. Actually, while I was waiting for a feedback I made a proof of concept implementation which turns out to be relatively straightforward task. For the parser part I have to add only a few more lines (excluding sanity checks): void Shader::_computeShaderDefines() { ... if (keyword == "import_defines") _parseShaderDefines(str, _shaderDefines); else if (keyword == "requires") _parseShaderDefines(str, _shaderRequirements); else if (keyword == "repeat_begin") { ShaderDefines shaderCodeBlockIdentifers; _parseShaderDefines(str, shaderCodeBlockIdentifers); ShaderCodeBlock shaderCodeBlock; shaderCodeBlock._begin = eol; shaderCodeBlock._end = std::string::npos; shaderCodeBlock._identifier = *shaderCodeBlockIdentifers.begin(); _shaderCodeBlocks.push_back(shaderCodeBlock); } else if (keyword == "repeat_end") { ShaderCodeBlock& shaderCodeBlock = _shaderCodeBlocks.back(); shaderCodeBlock._end = _shaderSource.find_last_not_of(" \t", pos - 8); } ... } In terms of code bloat in shaders, the #pragma(tic) shader composition ensures that the final code passed the OpenGL will have all the unimplemented paths removed so performance won't be an issue. For developers code bloat in shaders is an potential issue, one thing you do to help would be to wrap up all the lighting calls into a small set of functions that are called from the main, these functions are implemented in separate shaders that handle all the different code paths so at least the complexity is kept in one place and can be reused easily. Agreed. A second possibility would be to have developers auto generate shaders so avoid creating bloated shaders directly. A third approach might be to have the ability to provide a custom parser to the OSG so that it can handle custom syntax that developers feel suits their needs better than the default set of features provided by the core #pragma(tic) shader composition. Third approach is the approach I like most. I wonder what others have to say about this, though... Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Am 14.01.2016 um 11:56 schrieb Robert Milharcic: On 14.1.2016 9:52, Sebastian Messerschmidt wrote: Hi Robert, This seems more complicated than needed. Why not pass the number of lights as a compile time constant #pragma import_defines (NUM_LIGHTS) shader_state->setDefine("NUM_LIGHTS",12); and use uniform arrays: uniform vec4 u_LightColor[NUM_LIGHTS]; for (int i = 0; i < NUM_LIGHTS;++i) { light+=calcLight(u_LightColor[i], ...): } I feel your approach will bloat the preprocessor code path and will complicate the use. Hi Sebastian, First, thank you for your input. Yes, that is more or less the same approach I'm currently using. The downside of this approach is that it requires additional nontrivial code logic for the uniform array management (u_LightColor) and that is why I started to look at the alternatives. What could be more complicated there than to setup individual uniforms? Sorry this doesn't pass as a valid argument. If you have to hold the number of used lights somewhere you can hold a reference to the uniform as well. There is also an upper limit for the size of the array that needs to be taken into account. At least 512. If this is not enough you can use Uniform buffer objects (UBO)[1] or Shader Storage Blocks[2] which support If this is not enough for your light-count you will probably hit performance problems first. Also, the loop represents unnecessary overhead (though, this is not a problem on a never hardware). That's an assumption of yours. Usually constant folded loops with single return and without break, continue-statements are unrolled by the compiler. I'll accept performance comparisons however ;) On the other hand, my suggestion fits well into existing pragmatic shader composition logic and probably has less downsides. Downside is that you're trying to invent a meta-language here out of reasons that I commented on. The downside of your approach is a preprocessor language with no clear advantages over the tools already at your disposal. So to say, the current language is already turing-complete and you're trying to put some syntactic sugar on top, which adds some high degree of complexity to the parser and to the shader-code. An alternative for you is to manage this part yourself by simply overriding the parts managing the define-states. Maybe Robert O. can fill in on the details here. Cheers Sebastian [1]https://www.opengl.org/wiki/Interface_Block_%28GLSL%29#Uniform_blocks [2]https://www.opengl.org/wiki/Interface_Block_%28GLSL%29#Shader_storage_blocks Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Sebastian, First of all, the lightning shader only illustrates one of the cases where (optionally) repeating a code block containing substitution parameter can be useful. I used the multi-light lightning as an illustration only. First, thank you for your input. Yes, that is more or less the same approach I'm currently using. The downside of this approach is that it requires additional nontrivial code logic for the uniform array management (u_LightColor) and that is why I started to look at the alternatives. What could be more complicated there than to setup individual uniforms? Sorry this doesn't pass as a valid argument. If you have to hold the number of used lights somewhere you can hold a reference to the uniform as well. Sorry, but that is not what I had in mind. The problem here is the management of the array uniform's content and not the reference to it or the light count etc. Let say I only want to disable one of the lights, say LIGHT0 eg. stateset->setDefines("LIGHT0", osg::StateAttribute::OFF). What will you do? There is also an upper limit for the size of the array that needs to be taken into account. At least 512. If this is not enough you can use Uniform buffer objects (UBO)[1] or Shader Storage Blocks[2] which support If this is not enough for your light-count you will probably hit performance problems first. Yes, that is true. The upper limit is not a problem for this specific multi-light problem. Also, the loop represents unnecessary overhead (though, this is not a problem on a never hardware). That's an assumption of yours. Usually constant folded loops with single return and without break, continue-statements are unrolled by the compiler. I'll accept performance comparisons however ;) Yes, you are right about that. The constant loop will most probably be unrolled by the compiler. Of courses, that is another assumption on top of the previous assumption :) On the other hand, my suggestion fits well into existing pragmatic shader composition logic and probably has less downsides. Downside is that you're trying to invent a meta-language here out of reasons that I commented on. The downside of your approach is a preprocessor language with no clear advantages over the tools already at your disposal. So to say, the current language is already turing-complete and you're trying to put some syntactic sugar on top, which adds some high degree of complexity to the parser and to the shader-code. Exactly, that was my intention, to add a higher degree of complexity and hopefully solve some problems that "turing-complete" language can't. An alternative for you is to manage this part yourself by simply overriding the parts managing the define-states. Maybe Robert O. can fill in on the details here. Cheers Sebastian Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Robert M. I went through this thread fast and I see you are trying (at least your show case) is lighting and use of shader composition. The approach you are taking is what I was using too, some years ago. But there are other methods that does not require any mods and will work just fine with the existing shader composition features. You can for example encode all the light attributes into a texture buffer object (think of this as an image where each float texel is one light attribute like color, etc). Have a look at this, it is Forward+ implementation in opensource project https://www.youtube.com/watch?v=beSkETJ_vgY We are releasing a new version with F+ lighting available these days, so you might want to keep an eye on it. Cheers, Nick On Thu, Jan 14, 2016 at 3:20 PM, Robert Osfieldwrote: > Hi Robert M. et. al. > > I don't have any answers/recommendations at this stage but one first > reading the proposal has relative to traditional C/C++ features seems > a bit out of place. > > #pragma(tic) shader composition currently have a very close mapping to > C macro's, my hope has always been that because of this close mapping > it'd be quick to pick up and use - this is one of the key reasons why > I went for this approach to shader composition. > > This makes me wonder if C/C++ features itself might be able to inspire > any proposed extensions to #pragma(tic) shader composition. > > Robert. > ___ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > -- trajce nikolov nick ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Robert M. et. al. I don't have any answers/recommendations at this stage but one first reading the proposal has relative to traditional C/C++ features seems a bit out of place. #pragma(tic) shader composition currently have a very close mapping to C macro's, my hope has always been that because of this close mapping it'd be quick to pick up and use - this is one of the key reasons why I went for this approach to shader composition. This makes me wonder if C/C++ features itself might be able to inspire any proposed extensions to #pragma(tic) shader composition. Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Hi Sebastian , On 14.1.2016 15:47, Sebastian Messerschmidt wrote: Am 14.01.2016 um 15:01 schrieb Robert Milharcic: Hi Sebastian, First of all, the lightning shader only illustrates one of the cases where (optionally) repeating a code block containing substitution parameter can be useful. I used the multi-light lightning as an illustration only. First, thank you for your input. Yes, that is more or less the same approach I'm currently using. The downside of this approach is that it requires additional nontrivial code logic for the uniform array management (u_LightColor) and that is why I started to look at the alternatives. What could be more complicated there than to setup individual uniforms? Sorry this doesn't pass as a valid argument. If you have to hold the number of used lights somewhere you can hold a reference to the uniform as well. Sorry, but that is not what I had in mind. The problem here is the management of the array uniform's content and not the reference to it or the light count etc. Let say I only want to disable one of the lights, say LIGHT0 eg. stateset->setDefines("LIGHT0", osg::StateAttribute::OFF). What will you do? Let's say you have a fixed maximum on N, than you create a UBO/Array of this size and provide a count-uniform for the maximum valid entries. If a light gets disabled, you simply remove it, copy it to the back and set your count to N-1. In the shader you simply loop from 0 to count instead of N. That might break compiler optimization, but it won't hurt too much I guess. When using the setDefine, OSG will have to issue a recompile of this new variant, which will degrade performance if all combinations are needed. Assume 16 Lightsource, that will produce 65536 possible shader programs ... and that is only 16, not 500, or 1000 ... Having 1024 individually switchable Lightsources would totally wreck your idea of having an alternative to my solution. 2^1024 might exceed the numbers of atoms in the known universe, so there is not a remote chance to solve this with shader combinations... The question was purely rhetorical. I just wanted to prove my point regarding the uniform's content management vs already provided setDefines("LIGHT0", osg::StateAttribute::OFF). I didn't expect all that. Sorry for the fuzz :) BTW, I'm not planing to toggle all possible on/off combinations just to see all the permutations, the normal graph usage is what I'm after. There is also an upper limit for the size of the array that needs to be taken into account. At least 512. If this is not enough you can use Uniform buffer objects (UBO)[1] or Shader Storage Blocks[2] which support If this is not enough for your light-count you will probably hit performance problems first. Yes, that is true. The upper limit is not a problem for this specific multi-light problem. Even so, UBOs support in the order of ten-tousands. If this is still isn't enough, a texture will provide maximum space. Might be your example, but the number of individual uniforms is less than that. And putting a heap of uniforms into the stateset will fasten the handbrake on the CPU side. Also, the loop represents unnecessary overhead (though, this is not a problem on a never hardware). That's an assumption of yours. Usually constant folded loops with single return and without break, continue-statements are unrolled by the compiler. I'll accept performance comparisons however ;) Yes, you are right about that. The constant loop will most probably be unrolled by the compiler. Of courses, that is another assumption on top of the previous assumption :) On the other hand, my suggestion fits well into existing pragmatic shader composition logic and probably has less downsides. Downside is that you're trying to invent a meta-language here out of reasons that I commented on. The downside of your approach is a preprocessor language with no clear advantages over the tools already at your disposal. So to say, the current language is already turing-complete and you're trying to put some syntactic sugar on top, which adds some high degree of complexity to the parser and to the shader-code. Exactly, that was my intention, to add a higher degree of complexity and hopefully solve some problems that "turing-complete" language can't. Turing complete solves all computable problems ;-) I do understand your motivation, but I still don't see the gain really. I've presented some alternative ways to solve your problem, as I came across some of those challenges too. The idea Robert mentioned might be a good one, basically we could use some kind of callback to let the user-code preprocess the shader, wait actually we can already do this, when it is loaded via a LoadCallback :-) Actually I'm preprocessing my shader code when it's loaded to perform "include" and automated shader-define setup, so this might work for your "loop" too. That would defeat the purpose of the #pragma(tic) shader
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
Am 14.01.2016 um 15:01 schrieb Robert Milharcic: Hi Sebastian, First of all, the lightning shader only illustrates one of the cases where (optionally) repeating a code block containing substitution parameter can be useful. I used the multi-light lightning as an illustration only. First, thank you for your input. Yes, that is more or less the same approach I'm currently using. The downside of this approach is that it requires additional nontrivial code logic for the uniform array management (u_LightColor) and that is why I started to look at the alternatives. What could be more complicated there than to setup individual uniforms? Sorry this doesn't pass as a valid argument. If you have to hold the number of used lights somewhere you can hold a reference to the uniform as well. Sorry, but that is not what I had in mind. The problem here is the management of the array uniform's content and not the reference to it or the light count etc. Let say I only want to disable one of the lights, say LIGHT0 eg. stateset->setDefines("LIGHT0", osg::StateAttribute::OFF). What will you do? Let's say you have a fixed maximum on N, than you create a UBO/Array of this size and provide a count-uniform for the maximum valid entries. If a light gets disabled, you simply remove it, copy it to the back and set your count to N-1. In the shader you simply loop from 0 to count instead of N. That might break compiler optimization, but it won't hurt too much I guess. When using the setDefine, OSG will have to issue a recompile of this new variant, which will degrade performance if all combinations are needed. Assume 16 Lightsource, that will produce 65536 possible shader programs ... and that is only 16, not 500, or 1000 ... Having 1024 individually switchable Lightsources would totally wreck your idea of having an alternative to my solution. 2^1024 might exceed the numbers of atoms in the known universe, so there is not a remote chance to solve this with shader combinations... There is also an upper limit for the size of the array that needs to be taken into account. At least 512. If this is not enough you can use Uniform buffer objects (UBO)[1] or Shader Storage Blocks[2] which support If this is not enough for your light-count you will probably hit performance problems first. Yes, that is true. The upper limit is not a problem for this specific multi-light problem. Even so, UBOs support in the order of ten-tousands. If this is still isn't enough, a texture will provide maximum space. Might be your example, but the number of individual uniforms is less than that. And putting a heap of uniforms into the stateset will fasten the handbrake on the CPU side. Also, the loop represents unnecessary overhead (though, this is not a problem on a never hardware). That's an assumption of yours. Usually constant folded loops with single return and without break, continue-statements are unrolled by the compiler. I'll accept performance comparisons however ;) Yes, you are right about that. The constant loop will most probably be unrolled by the compiler. Of courses, that is another assumption on top of the previous assumption :) On the other hand, my suggestion fits well into existing pragmatic shader composition logic and probably has less downsides. Downside is that you're trying to invent a meta-language here out of reasons that I commented on. The downside of your approach is a preprocessor language with no clear advantages over the tools already at your disposal. So to say, the current language is already turing-complete and you're trying to put some syntactic sugar on top, which adds some high degree of complexity to the parser and to the shader-code. Exactly, that was my intention, to add a higher degree of complexity and hopefully solve some problems that "turing-complete" language can't. Turing complete solves all computable problems ;-) I do understand your motivation, but I still don't see the gain really. I've presented some alternative ways to solve your problem, as I came across some of those challenges too. The idea Robert mentioned might be a good one, basically we could use some kind of callback to let the user-code preprocess the shader, wait actually we can already do this, when it is loaded via a LoadCallback :-) Actually I'm preprocessing my shader code when it's loaded to perform "include" and automated shader-define setup, so this might work for your "loop" too. Cheers Sebastian An alternative for you is to manage this part yourself by simply overriding the parts managing the define-states. Maybe Robert O. can fill in on the details here. Cheers Sebastian Cheers, Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org ___ osg-users mailing list
Re: [osg-users] Pragmatic shader - a new #pragma directive proposition
On 14.1.2016 15:20, Robert Osfield wrote: Hi Robert M. et. al. I don't have any answers/recommendations at this stage but one first reading the proposal has relative to traditional C/C++ features seems a bit out of place. #pragma(tic) shader composition currently have a very close mapping to C macro's, my hope has always been that because of this close mapping it'd be quick to pick up and use - this is one of the key reasons why I went for this approach to shader composition. This makes me wonder if C/C++ features itself might be able to inspire any proposed extensions to #pragma(tic) shader composition. Robert. Hi Robert O. If I'm not mistaken, the #pragmadirective is used by the C/C++ preprocessor for providing additional information, beyond what the language itself can offer. I thought this was the main inspiration for #pragma(tic) shader composition. Anyway, based on feedback I'm now convinced that my proposition isn't that useful as I thought :) and on that note, I rest my case. Cheers Robert Milharcic ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org