Hi
I'm working on a small vertex shader using GLSL for my skydome. It
affects color to vertices according their y. It makes a linear gradient
between 2 colors.
The problem is:
- I am transferring 4 uniforms to pass top color (4f) and y (1f) and
bottom color (4f) and y (1f)
- my formula to get the color according altitude is:
color4f=bottomcolor4f+(topcolor4f-bottomcolor4f)*
(gl_Vertex.y-bottomy1f)/(topy1f-bottomy1f)
So what bottomy1f and topy1f should I pass to the shader to be at the
same "state of projection" than gl_Vertex.y (I guess... I am sure that
it is not the original - by "original", I mean the one in the FBO - y of
the top and bottom vertices) or perhaps there is something different
from gl_Vertex to get the original 3D-coordinate in the shader.
Thanks
Cathy
|
|
0
|
|
|
|
Reply
|
Cathy
|
3/13/2009 8:04:08 AM |
|
No answer? Is that a hard question or is it hard to understand what I want?
|
|
0
|
|
|
|
Reply
|
Cathy
|
3/13/2009 3:24:03 PM
|
|
Cathy wrote:
> No answer? Is that a hard question or is it hard to understand what I
> want?
This is not a immediate response hotline. Give some people a chance to read
your post. And of those people at least one wonders, why you don't simply
use a 1D texture in clamping mode and apropriate texture coordinates...
Wolfgang
--
OpenGL tip #42:
How to exactly map texture texels to screen pixels:
<http://preview.tinyurl.com/cgndc8>
|
|
0
|
|
|
|
Reply
|
Wolfgang
|
3/13/2009 4:23:05 PM
|
|
Cathy wrote:
> Hi
> I'm working on a small vertex shader using GLSL for my skydome. It
> affects color to vertices according their y. It makes a linear gradient
> between 2 colors.
>
> The problem is:
> - I am transferring 4 uniforms to pass top color (4f) and y (1f) and
> bottom color (4f) and y (1f)
> - my formula to get the color according altitude is:
> color4f=bottomcolor4f+(topcolor4f-bottomcolor4f)*
> (gl_Vertex.y-bottomy1f)/(topy1f-bottomy1f)
>
> So what bottomy1f and topy1f should I pass to the shader to be at the
> same "state of projection" than gl_Vertex.y
Answering your next question (next post) more than this; no, the
question is not clear to me and I specifically don't understand the last
part of the sentence above. But then there's a lot of OpenGL and GLSL
not clear to me :( And now that Wolfgang has got involved, I really
should keep quiet. On the other hand, /I/ might learn something.
Any of the following do what the first line makes explicit:
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = ftransform();
so can you pass (two?) untransformed vertices that mark the beginning
and end of the linear interpolation, transform them, and then
interpolate based on gl_Position.y1, gl_Position.y2?
But this would be applied only to vertices that specify primitives.
So maybe you need to work in the fragment shader?
(I guess... I am sure that
> it is not the original - by "original", I mean the one in the FBO - y of
> the top and bottom vertices) or perhaps there is something different
> from gl_Vertex to get the original 3D-coordinate in the shader.
>
Best regards,
Jon C.
|
|
0
|
|
|
|
Reply
|
Jonathan
|
3/13/2009 4:51:57 PM
|
|
> This is not a immediate response hotline. Give some people a chance to read
> your post.
Shame on me, Wolfgang, I am so used to have an answer within the hour
and I was so sure that if understood, this question is an easy-to-answer
one for those who know that I was sincerely wondering if the
explanations of my problem were not clear enough.
> And of those people at least one wonders, why you don't simply
> use a 1D texture in clamping mode and apropriate texture coordinates...
In fact, I decided not to use texture, because I was sure it was more
efficient with just colors and because it is really easier to change the
gradient of the sky according the time of the day just shifting the
values of the 2 vec4 uniforms than creating another texture.
I'm gonna wait for the answer, sorry for my impatience.
Cathy
|
|
0
|
|
|
|
Reply
|
Cathy
|
3/13/2009 5:06:22 PM
|
|
Hi John and thanks to try to answer even if you are not sure, I do the
same when I have an idea (and it is worse for me, my skill is really
low). I do believe that's the way NGs work.
> I specifically don't understand the last
> part of the sentence above.
As I said later on, I am quite sure that the GLSL gl_Vertex.x,
gl_Vertex.y and gl_Vertex.z are not the values passed via the OpenGL
glVertex3f(x,y,z), they were already transformed.
I tried with this GLSL vertex shader:
"
uniform float altmin;
uniform float altmax;
uniform vec4 colmin;
uniform vec4 colmax;
void main(void)
{
gl_Position=ftransform();
gl_BackColor=colmin+(colmax-colmin)*(gl_Vertex.y-altmin)/(altmax-altmin);
}
"
And the result is quite... psychedelic:
http://img10.imageshack.us/img10/7854/psyche.jpg
So I guess the GLSL gl_Vertex received some transformations from the
vector passed to OpenGL via VBO or glVertex(,,) as altmin and altmax are
respectively the y-component of the bottom and top vertices of the dome
passed to OpenGL.
Is it clearer?
Thanks you all
Cathy
|
|
0
|
|
|
|
Reply
|
Cathy
|
3/13/2009 5:39:02 PM
|
|
Cathy wrote:
> Hi John and thanks to try to answer even if you are not sure, I do the
> same when I have an idea (and it is worse for me, my skill is really
> low). I do believe that's the way NGs work.
>
>> I specifically don't understand the last part of the sentence above.
>
> As I said later on, I am quite sure that the GLSL gl_Vertex.x,
> gl_Vertex.y and gl_Vertex.z are not the values passed via the OpenGL
> glVertex3f(x,y,z), they were already transformed.
> I tried with this GLSL vertex shader:
> "
> uniform float altmin;
> uniform float altmax;
> uniform vec4 colmin;
> uniform vec4 colmax;
> void main(void)
> {
> gl_Position=ftransform();
> gl_BackColor=colmin+(colmax-colmin)*(gl_Vertex.y-altmin)/(altmax-altmin);
> }
> "
> And the result is quite... psychedelic:
> http://img10.imageshack.us/img10/7854/psyche.jpg
>
> So I guess the GLSL gl_Vertex received some transformations from the
> vector passed to OpenGL via VBO or glVertex(,,) as altmin and altmax are
> respectively the y-component of the bottom and top vertices of the dome
> passed to OpenGL.
>
> Is it clearer?
>
Maybe a little.
We've seen the vertex shader; I assume that you have loaded no fragment
shader.
Could we see the 'display' function --- as minimal a version as possible?
Someone correct me if I'm wrong, but is not that 'main' function above
applied to every vertex (whether specified via VBO or simple glVertex*
call). I cannot see that the vertex (gl_Vertex) would have been
transformed, after all that's what gl_Position=ftransform() does.
Best regards,
Jon C.
|
|
0
|
|
|
|
Reply
|
Jonathan
|
3/13/2009 6:04:32 PM
|
|
Cathy wrote:
> I'm gonna wait for the answer, sorry for my impatience.
You don't have to wait. What you attemt to do is a linear interpolation.
GLSL provides a builtin function for this: mix
<http://www.opengl.org/wiki/GLSL_:_common_mistakes#Linear_Interpolation.2C_lerp.2C_mix>
Using that your code reduces to
color4f = mix(
bottomcolor4f,
topcolor4f,
(gl_Vertex.y-bottomy1f)/(topy1f-bottomy1f) );
You may like this one
<http://www.opengl.org/sdk/libs/OpenSceneGraph/glsl_quickref.pdf>
If your intention is colouring a skydome, a height depending gradient is not
very satisfying. BTDT. In my experience a very good, but easy to implement
thing to do is precalculating some cubemaps for several daytimes and put
those on the skydome.
--
OpenGL tip #42:
How to exactly map texture texels to screen pixels:
<http://preview.tinyurl.com/cgndc8>
|
|
0
|
|
|
|
Reply
|
Wolfgang
|
3/13/2009 6:39:56 PM
|
|
> color4f = mix(
> bottomcolor4f,
> topcolor4f,
> (gl_Vertex.y-bottomy1f)/(topy1f-bottomy1f) );
I tried and as it does the same, the result is the same. So where is the
mistake?
So you say that the OpenGL glVertex and the GLSL gl_Vertex hold the same
coordinates?
> If your intention is colouring a skydome, a height depending gradient is not
> very satisfying. BTDT. In my experience a very good, but easy to implement
> thing to do is precalculating some cubemaps for several daytimes and put
> those on the skydome.
Ok I start looking at it right now, I would like to make the previous
shader work, just to understand the mistake.
Thanks again Wolfgang
|
|
0
|
|
|
|
Reply
|
Cathy
|
3/13/2009 7:28:07 PM
|
|
Cathy wrote:
>> color4f = mix(
>> bottomcolor4f,
>> topcolor4f,
>> (gl_Vertex.y-bottomy1f)/(topy1f-bottomy1f) );
>
> I tried and as it does the same, the result is the same. So where is the
> mistake?
Hard to tell, without seeing the rest of the picture.
> So you say that the OpenGL glVertex and the GLSL gl_Vertex hold the same
> coordinates?
Yes.
--
OpenGL tip #42:
How to exactly map texture texels to screen pixels:
<http://preview.tinyurl.com/cgndc8>
|
|
0
|
|
|
|
Reply
|
Wolfgang
|
3/13/2009 8:00:46 PM
|
|
Cathy wrote:
> As I said later on, I am quite sure that the GLSL gl_Vertex.x,
> gl_Vertex.y and gl_Vertex.z are not the values passed via the OpenGL
> glVertex3f(x,y,z), they were already transformed.
> I tried with this GLSL vertex shader:
> "
> uniform float altmin;
> uniform float altmax;
> uniform vec4 colmin;
> uniform vec4 colmax;
> void main(void)
> {
> gl_Position=ftransform();
> gl_BackColor=colmin+(colmax-colmin)*(gl_Vertex.y-altmin)/(altmax-altmin);
> }
> "
> And the result is quite... psychedelic:
> http://img10.imageshack.us/img10/7854/psyche.jpg
>
> So I guess the GLSL gl_Vertex received some transformations from the
> vector passed to OpenGL via VBO or glVertex(,,) as altmin and altmax are
> respectively the y-component of the bottom and top vertices of the dome
> passed to OpenGL.
>
> Is it clearer?
>
> Thanks you all
>
> Cathy
Hello Cathy:
I'm an amateur when it comes to GLSL but I took your code into ATI
RenderMonkey rewrote the vertex shader as follows:
uniform float altmin;
uniform float altmax;
uniform vec4 colmin;
uniform vec4 colmax;
varying vec4 frag_color;
void main(void)
{
gl_Position=ftransform();
frag_color=colmin+(colmax-colmin)*(gl_Vertex.y-altmin)/(altmax-altmin);
}
added a fragment shader as follows:
varying vec4 frag_color;
void main(void)
{
gl_FragColor = frag_color;
}
Set the uniforms to altmin = -50, altmax = 50, colmin = blue, colmax =
red. And ran the shader against the default sphere object.
The sphere displayed a smooth transition from blue on the bottom to red
on the top with a nice blue red gradient in the middle. So, the formula
you are using works but being that I'm an amateur, I don't know if
gl_BackColor you're using is appropriate in this situation so I avoided
using it in my code above.
Michael
|
|
0
|
|
|
|
Reply
|
Michael
|
3/14/2009 2:33:22 AM
|
|
> uniform float altmin;
> uniform float altmax;
> uniform vec4 colmin;
> uniform vec4 colmax;
> varying vec4 frag_color;
> void main(void)
> {
> gl_Position=ftransform();
> frag_color=colmin+(colmax-colmin)*(gl_Vertex.y-altmin)/(altmax-altmin);
> }
>
> added a fragment shader as follows:
>
> varying vec4 frag_color;
> void main(void)
> {
> gl_FragColor = frag_color;
> }
Hello Michael
That's the solution, it works quite well now, here is the result from
clear blue to dark blue:
http://img17.imageshack.us/img17/7757/nicep.jpg
Strange that gl_BackColor is not what expected!
I'm Gonna have a look at that rendermonkey.
Thanks
Cathy
|
|
0
|
|
|
|
Reply
|
Cathy
|
3/14/2009 7:13:21 AM
|
|
On Mar 13, 6:06=A0pm, Cathy <n...@no.fr> wrote:
> In fact, I decided not to use texture, because I was sure it was more
> efficient with just colors and because it is really easier to change the
> gradient of the sky according the time of the day just shifting the
> values of the 2 vec4 uniforms than creating another texture.
If you change your mind about using textures, have a look at (http://
www.geocities.com/ngdash/whitepapers/skydomecolor.html). It's a very
simple and efficient approach that can produce surprisingly good
results. The idea is to encode the gradients in a 2D texture, with
altitude indexing into one axis (CLAMP), and time of day into the
other axis (REPEAT). Compute the altitude into a varying, send the
time of day from your application into a uniform, and sample the
skycolor in the fragment shader with bilinear filtering. It looks
great and you don't have to update uniforms across the sky dome (can
be expensive). You can get with using very small textures so
performance will be excellent (I guess, as fast as your arithmetic
approach if the sampling latency can be hidden by other ALU
instructions). Another idea to extend this approach could be to use a
cubemap where each face stores the skycolors for a specific season (2
months).
regards,
Nicolai de Haan Br=F8gger
|
|
0
|
|
|
|
Reply
|
ndhb78
|
3/14/2009 1:33:25 PM
|
|
> If you change your mind about using textures, have a look at (http://
> www.geocities.com/ngdash/whitepapers/skydomecolor.html). It's a very
> simple and efficient approach that can produce surprisingly good
> results. The idea is to encode the gradients in a 2D texture, with
> altitude indexing into one axis (CLAMP), and time of day into the
> other axis (REPEAT). Compute the altitude into a varying, send the
> time of day from your application into a uniform, and sample the
> skycolor in the fragment shader with bilinear filtering. It looks
> great and you don't have to update uniforms across the sky dome (can
> be expensive). You can get with using very small textures so
> performance will be excellent (I guess, as fast as your arithmetic
> approach if the sampling latency can be hidden by other ALU
> instructions). Another idea to extend this approach could be to use a
> cubemap where each face stores the skycolors for a specific season (2
> months).
>
> regards,
> Nicolai de Haan Br�gger
Thanks Nicolai, it seems realistic and efficient.
I will try that.
Friendly
Cathy
|
|
0
|
|
|
|
Reply
|
Cathy
|
3/14/2009 6:47:27 PM
|
|
Cathy wrote:
>> color4f = mix(
>> bottomcolor4f,
>> topcolor4f,
>> (gl_Vertex.y-bottomy1f)/(topy1f-bottomy1f) );
>
> I tried and as it does the same, the result is the same. So where is the
> mistake?
You may have solved it already, but with shaders, I debug mostly using
visual cues. So add a fragment shader so you can visualize variables as
colors.
For example, if you're really paranoid, in the fragment shader, output
the pure bottomcolor4f or topcolor4f, to make sure they are what you
expect them. Then, visualize the division in the color4f=... expression
above.
At some point, one of the variables you're using (and with GLSL shaders,
it's almost never too many) isn't behaving as expected. Break things
down to all the different inputs, visualize those, and one of them will
be the cue.
Ruud
|
|
0
|
|
|
|
Reply
|
Ruud
|
3/18/2009 9:55:17 AM
|
|
> You may have solved it already, but with shaders, I debug mostly using
> visual cues. So add a fragment shader so you can visualize variables as
> colors.
Thanks Ruud I keep the hint
Cathy
|
|
0
|
|
|
|
Reply
|
Cathy
|
3/18/2009 3:23:34 PM
|
|
|
15 Replies
384 Views
(page loaded in 1.029 seconds)
|