GLSL: how to define input and output properly

Started by
30 comments, last by Spikx 14 years, 6 months ago
Hello there, in the past I always used NVidia Cg for my Shaders in my applications. For a recent project we decided to switch to GLSL in order to try it out and learn it. I have a little bit of trouble adjusting to it. One thing I can't wrap my head around is how to define input and output data in a proper way. It seems GLSL is very "loose". If I write
varying vec3 lightDir;
in both the vertex and the fragment shader, it seems its data is "magically" ;) available in both shaders. Anyway what I would like to hear from the GLSL users is, how you "properly" define your input and output variables. For instance, in Cg you can specifically assign the data of a hardware register to a variable. In Cg I always used structs like
struct a2v 
{
	float4 pos       : POSITION;
	float3 normal    : NORMAL;
	float2 texcoord  : TEXCOORD0;
	float4 tangent   : TEXCOORD1;
	float3 binormal  : TEXCOORD2;
};
for the input of the vertex shader and
struct v2f
{
	float4 color	: COLOR0;
	float4 hpos	: POSITION;
	float2 texcoord	: TEXCOORD0;
	float3 vpos	: TEXCOORD1;
	float3 normal	: TEXCOORD2;
	float3 tangent	: TEXCOORD3;
	float3 binormal	: TEXCOORD4;
	float3 view	: TEXCOORD5;
	float3 scale	: TEXCOORD6;
};
for the input of the fragment shader, for example. But what is a good, clean and readable way to do the same in GLSL?
Advertisement
Im not 100% sure what youre meaning based on your code but perhaps the following from the glsl spec is helpful

4.4 Parameter Qualifiers
Parameters can have these qualifiers.
Qualifier Meaning
< none: default > same is in
in ---- for function parameters passed into a function
out ---- for function parameters passed back out of a function, but not initialized
for use when passed in
inout ---- for function parameters passed both into and out of a function
Yes, but how do I assign them to hardware registers? How will I know which variables will be the data that OpenGL passes on to them? It seems this is not possible with GLSL, so I am wondering how GLSL users are dealing with that...
I know that there are all the predefined gl_ variables, which are also writeable it seems. But I can't rename those, can I?
You can use glGetAttribLocation, to get the index of a variable in a GLSL shader program. Alternatively you can decide them yourself and set them for each variable with glBindAttribLocation.
You specify what arrays go into which variable with glVertexAttribPointer, when setting what arrays to use.

Some information here: http://www.opengl.org/wiki/GlVertexAttribPointer.
Quote:Original post by Erik Rufelt
You can use glGetAttribLocation, to get the index of a variable in a GLSL shader program. Alternatively you can decide them yourself and set them for each variable with glBindAttribLocation.
You specify what arrays go into which variable with glVertexAttribPointer, when setting what arrays to use.

Some information here: http://www.opengl.org/wiki/GlVertexAttribPointer.
Hmmm. Ok, but is that how you usually work with GLSL? The goal of the hardware register assignments in Cg is, that you don't have to use any additional code in order to pass per vertex and per object data to the Shader and just use all the normal OpenGL calls/states instead. And furthermore pass down the data in the pipeline on the hardware with variable names that you chose yourself (and not just gl_Color, gl_MultiTexCoord0 etc.).
You pass the name of the variable to glGetAttribLocation, and just refer to it afterward with an integer ID instead. I guess it's a little more code..
In GL3 texture arrays etc. aren't there anymore, everything is done with your own names, so somehow you need to tell OpenGL which one is which.
Quote:Original post by Erik Rufelt
You pass the name of the variable to glGetAttribLocation, and just refer to it afterward with an integer ID instead. I guess it's a little more code..
Well, I'd say it's quite a bit more code ;). You have to get and store the location of every variable. This also means that you would have to adjust your code for every shader. It makes things much more complicated.

Do people usually just use gl_Color, gl_MultiTexCoord0-x etc. instead?


Quote:In GL3 texture arrays etc. aren't there anymore, everything is done with your own names, so somehow you need to tell OpenGL which one is which.
Ah, speaking of textures. In Cg you could assign the texture units of the hardware to a variable. In GLSL it seems that the texture units are simply assigned to any uniform samplerXD variables? As far as I observed it, if I have
uniform sampler2D foo1;uniform sampler2D foo2;
in my shader, foo1 is assigned to texture unit 0 (GL_TEXTURE0) and foo2 is assigned to texture unit 1 (GL_TEXTURE1). Is that correct or is the assignment decided differently?
Quote:Original post by Spikx
Well, I'd say it's quite a bit more code ;). You have to get and store the location of every variable. This also means that you would have to adjust your code for every shader. It makes things much more complicated.

Do people usually just use gl_Color, gl_MultiTexCoord0-x etc. instead?


Previously yes, but they are gone in GL3 and there's not really any point to using them anyway. It won't be any more code if you use the same names all the time, the only difference is you decide the names in your own shader loading function, instead of Nvidia deciding them in the CG code or wherever.
Just always link "myTexCoord0" to the same slot.

BTW with texture arrays I meant texture coord arrays of course.
With textures you can get the texture sampler position with glGetUniformLocation and set the texture ID used for each sampler. See http://www.opengl.org/wiki/GLSL_:_common_mistakes (scroll down to binding textures). And that page might clear some other things up too.
Quote:Original post by Erik RufeltPreviously yes, but they are gone in GL3 and there's not really any point to using them anyway. It won't be any more code if you use the same names all the time, the only difference is you decide the names in your own shader loading function, instead of Nvidia deciding them in the CG code or wherever.
No, you use your own variable name in Cg too. And you can do that without having any additional code of storing, getting and verifying the parameter id and then calling another function in order to set data for that parameter in your application (other than default OpenGL calls).


Quote:Original post by Erik RufeltBTW with texture arrays I meant texture coord arrays of course.
With textures you can get the texture sampler position with glGetUniformLocation and set the texture ID used for each sampler. See http://www.opengl.org/wiki/GLSL_:_common_mistakes (scroll down to binding textures). And that page might clear some other things up too.
Aaah, thx, that clears things up about the texture units :).
Quote:Original post by Spikx
No, you use your own variable name in Cg too. And you can do that without having any additional code of storing, getting and verifying the parameter id and then calling another function in order to set data for that parameter in your application (other than default OpenGL calls).


You specify the parameter ID with TEXCOORD0. Cg turns that into the correct number under the hood. Which OpenGL version do you use?
You can use those gl_TexCoord[0] etc. if you don't want to bother with it, unless you compile for GL3 without the compatibility bit set.

To use GLSL efficiently and cleanly you would implement your own "mini-cg" that tweaks all that to your own liking, and if you want you can write that so it will let you get away with not using extra code. It will obviously be more work than just going with the old version, until you get it set up, but if you do it to learn GLSL I would recommend going with GL3 anyway. Once you have it set up I think GL3 is better.
In GLSL the shader program contains both the fragment and vertex shader, and it's regarded as the same shader, so the variable name is the semantic. So if you have a variable in the vertex shader and in the fragment shader called 'lightDir' then it will be the same variable. It's bound to the name of the variable instead of the semantic 'TEXCOORD0' for example.

This topic is closed to new replies.

Advertisement