From: Renk T. <tho...@jy...> - 2012-10-24 08:40:36
|
> I haven't really been following this thread closely... are the > "tracers" basically occludes? Are they completely opaque? Yes, they're completely opaque. That's tracer.frag - if it gets a white gl_Color from the vertex shader, it's a real cloud and the fragment is dropped, if it gets any other color the pixel is that of a tracer it produces an opaque white pixel: void main(void) { if (gl_Color == vec4(1.0, 1.0, 1.0, 1.0)) // this is a real cloud {discard;} gl_FragColor = vec4 (1.0, 1.0, 1.0, 1.0); } 'occluders' would perhaps be a more intuitive name then... > One possible optimization for the cloud rendering would be to use > polygons that closely follow the outline of the sprite instead of > quads; this saves on fill costs. The tracer/occluder is supposed to deal with the whole cloud, not any individual sprite (individual sprites may be just a bit transparent even in the center, but a collection of 20 of them is no longer, and in any case doing it on a per-sprite basis means 20 times the load for the vertex shader). We don't know the shape of the cloud before we create them, and to generate a polygon representing in detail the opaque part of the final cloud which is a collection of sprites with varying transparency and looks different from various positions is something which sounds highly non-trivial to me. The tracer is just the simplest guess occluding part of the opaque core of the cloud. It doesn't need to be hugely efficient on an individual cloud, because there'll be hundreds of them in a row, so even if we get only 20 % of any individual cloud, the end result is that we get opaque everywhere after 10 clouds rather than doing a row of 200 everywhere. > Also, I'm pretty sure you don't want two-sided lighting for the tracers. Okay - I'll switch this off then. But that can't explain the depth buffer issue, can it? * Thorsten |
From: Renk T. <tho...@jy...> - 2012-10-24 11:27:44
|
> I realize that I'm confused about whether you are working on Stuart's > clouds in C++ or clouds in Nasal. They're the same now - there's an interface to generate a cloud from Nasal which is what I'm using, whereas Basic Weather uses and xml format for layer declaration, but for rendering purpose there is no difference. > How are you generating the tracer? I gather that it > doesn't use any textures. If a flag is set in the cloud definition, after a cloud (consisting of a number of sprites) has been generated, a tracer is inserted at the same position in the center of the cloud. Currently only works if you insert clouds from Nasal. Formally a tracer is a cloud with just a single sprite, but a cloud with a top shade factor set to zero (i.e. a pitch-black top) - which is why we know in the shader it can't be a real cloud. > Your shader seems like an expensive > way to toggle between tracers and real sprites; it would be much > better to not render the sprite geometry at all in your tracer pass. I basically don't - if a vertex not belonging to a tracer arrives in tracer.vert, all the vertex shader does is to move it out of the view frustrum (come to think of it, the if-statement in the fragment shader shouldn't even be necessary - sorry, this is just mess in progress). Also the effect currently declares a texture which I'm not using because at some point I wanted to test round tracers. > You should use a <color-mask type="vec4d">0 0 0 0</color-mask> > declaration to turn off color writes when rendering the tracers, since > you don't want them to actually appear in the output. That will save > you some fill costs. Thanks, that's very helpful. > As for not seeing much improvement when the terrain is occluded, I can > think of several possibilities. You said that "I've tested that I am > not vertex-shader dominated by discarding half the pixels of the > terrain in my field of view;" how did you do that? By putting if (gl_FragCoord.y > 300) {discard;} early into the terrain fragment shader. > but this > can only be done if the shader can't affect the Z output value. > Writing the fragment depth would do that (urban shader), but the > classic offenders are "discard" and alpha testing. Thanks for the pointers - I'll have a look. How come it works for clouds then? The normal cloud passes all use alpha testing... * Thorsten |
From: Tim M. <tim...@gm...> - 2012-10-24 13:38:21
|
On Wed, Oct 24, 2012 at 1:27 PM, Renk Thorsten <tho...@jy...> wrote: >> I realize that I'm confused about whether you are working on Stuart's >> clouds in C++ or clouds in Nasal. >> How are you generating the tracer? I gather that it >> doesn't use any textures. > > If a flag is set in the cloud definition, after a cloud (consisting of a number of sprites) has been generated, a tracer is inserted at the same position in the center of the cloud. Currently only works if you insert clouds from Nasal. Formally a tracer is a cloud with just a single sprite, but a cloud with a top shade factor set to zero (i.e. a pitch-black top) - which is why we know in the shader it can't be a real cloud. > >> Your shader seems like an expensive >> way to toggle between tracers and real sprites; it would be much >> better to not render the sprite geometry at all in your tracer pass. > > I basically don't - if a vertex not belonging to a tracer arrives in tracer.vert, all the vertex shader does is to move it out of the view frustrum (come to think of it, the if-statement in the fragment shader shouldn't even be necessary - sorry, this is just mess in progress). Also the effect currently declares a texture which I'm not using because at some point I wanted to test round tracers. > If I understand correctly, you have only one model of the cloud, which has a bunch of sprites and a few tracer polygons. I don't know if this is practical in the current system, but I'm saying that it would be better to draw only the tracers in the tracer pass and the sprites in the real pass as you do know which is which in advance. I do appreciate the clipping trick in the vertex shader :) >> As for not seeing much improvement when the terrain is occluded, I can >> think of several possibilities. You said that "I've tested that I am >> not vertex-shader dominated by discarding half the pixels of the >> terrain in my field of view;" how did you do that? > > By putting > > if (gl_FragCoord.y > 300) {discard;} > > early into the terrain fragment shader. OK > >> but this >> can only be done if the shader can't affect the Z output value. >> Writing the fragment depth would do that (urban shader), but the >> classic offenders are "discard" and alpha testing. > > Thanks for the pointers - I'll have a look. How come it works for clouds then? The normal cloud passes all use alpha testing... They don't write the Z buffer at all, do they? Tim |
From: Renk T. <tho...@jy...> - 2012-10-24 18:53:31
|
> If I understand correctly, you have only one model of the cloud, which > has a bunch of sprites and a few tracer polygons. I don't know if this > is practical in the current system, but I'm saying that it would be > better to draw only the tracers in the tracer pass and the sprites in > the real pass as you do know which is which in advance. I do > appreciate the clipping trick in the vertex shader :) I think it's two models - one containing the actual cloud sprites and one containing the tracer. Both run via both shaders, but the first pass only does real work for the tracers and discards real clouds, the second pass does work for real clouds but discards tracers. In principle it would be (marginally) better to do one pass for clouds and tracers each, since as you say we know up front which is which. In practice tracers need to inherit the movement of the clouds, so it doesn't do to just put models in, they need to inherit the visibility range, and I guess all this would require changes on the C++ level, duplicating or generalizing part of Stuart's cloud generating system. The expected performance gain is marginal - I can't even measure the difference between adding tracers without z-buffer write and not adding tracers. So I think for testing purposes it's okay to go with the scheme, it's not where the performance is burnt. > They don't write the Z buffer at all, do they? No, but what I mean is: I see that the first cloud pass for the tracers writes the z-buffer, because if I insert the tracers at the wrong altitude, they punch neat square holes into my real layer where the z-buffer says not to do the real cloud. This works in spite of the fact that the second pass uses alpha testing, as do all cloud effects currently declared. The tracers just don't do this for the terrain. But the second terrain pass as such is fine with the z-buffer. I have introduced a first pass for trees in render bin -1, and if I don't do the second tree pass I get neat tree-shaped holes punched into my terrain mesh and the expected performance bonus for not doing a lot of terrain pixels. So I know clouds write a z-buffer, and I know terrain reads a z-buffer - they just don't seem to use the same z-buffer. In which case the whole scheme doesn't work as advertized. Does that make any sense? Is there anything special about clouds? * Thorsten |
From: Renk T. <tho...@jy...> - 2012-11-07 07:55:04
|
> So I know clouds write a z-buffer, and I know terrain reads a z-buffer - > they just don't seem to use the same z-buffer. In which case the whole > scheme doesn't work as advertized. Does that make any sense? Is there > anything special about clouds? Seems I can't figure that one out on my own, so I abandoned the project. I guess I'll see then how the performance of overcast layers looks with a modern GPU and get a new computer then. * Thorsten |
From: Tim M. <tim...@gm...> - 2012-10-24 10:55:46
|
On Wed, Oct 24, 2012 at 10:40 AM, Renk Thorsten <tho...@jy...> wrote: >> I haven't really been following this thread closely... are the >> "tracers" basically occludes? Are they completely opaque? > > Yes, they're completely opaque. That's tracer.frag - if it gets a white gl_Color from the vertex shader, it's a real cloud and the fragment is dropped, if it gets any other color the pixel is that of a tracer it produces an opaque white pixel: > > void main(void) > { > if (gl_Color == vec4(1.0, 1.0, 1.0, 1.0)) // this is a real cloud > {discard;} > gl_FragColor = vec4 (1.0, 1.0, 1.0, 1.0); > } > > 'occluders' would perhaps be a more intuitive name then... Yes, I meant "occluders;" perhaps I was on "occludes" :) > >> One possible optimization for the cloud rendering would be to use >> polygons that closely follow the outline of the sprite instead of >> quads; this saves on fill costs. > > The tracer/occluder is supposed to deal with the whole cloud, not any individual sprite (individual sprites may be just a bit transparent even in the center, but a collection of 20 of them is no longer, and in any case doing it on a per-sprite basis means 20 times the load for the vertex shader). We don't know the shape of the cloud before we create them, and to generate a polygon representing in detail the opaque part of the final cloud which is a collection of sprites with varying transparency and looks different from various positions is something which sounds highly non-trivial to me. The tracer is just the simplest guess occluding part of the opaque core of the cloud. It doesn't need to be hugely efficient on an individual cloud, because there'll be hundreds of them in a row, so even if we get only 20 % of any individual cloud, the end result is that we get opaque everywhere after 10 clouds rather than doing a row of 200 everywhere. > I was thinking more of the sprite rendering, so my comment was a bit off-topic here. How are you generating the tracer? I gather that it doesn't use any textures. I realize that I'm confused about whether you are working on Stuart's clouds in C++ or clouds in Nasal. Your shader seems like an expensive way to toggle between tracers and real sprites; it would be much better to not render the sprite geometry at all in your tracer pass. >> Also, I'm pretty sure you don't want two-sided lighting for the tracers. > > Okay - I'll switch this off then. But that can't explain the depth buffer issue, can it? Probably not. You should use a <color-mask type="vec4d">0 0 0 0</color-mask> declaration to turn off color writes when rendering the tracers, since you don't want them to actually appear in the output. That will save you some fill costs. As for not seeing much improvement when the terrain is occluded, I can think of several possibilities. You said that "I've tested that I am not vertex-shader dominated by discarding half the pixels of the terrain in my field of view;" how did you do that? This optimization depends on being able to do an "early Z" test to not rasterize big regions of the terrain triangles and avoid running the terrain shaders on those pixels that will fail the Z test, but this can only be done if the shader can't affect the Z output value. Writing the fragment depth would do that (urban shader), but the classic offenders are "discard" and alpha testing. It's probably worth checking that the terrain shaders aren't doing those things. A quick look at terrain-default.eff shows that alpha-test is set to "transparent" which, IIRC, means that it is set based on whether or not the texture is transparent; it should probably just be "off." Tim |