PDA

View Full Version : Have problem to pass texture into shader.



SagoO
04-06-2011, 09:32 PM
Here is my fragment:


static const char *fragment_source = {

// texture global variable, set by application
"uniform sampler2DRect texture;"

"void main(void)"
"{"
//Read texture coordinates
"vec2 texCoord = gl_TexCoord[0].xy;"
//Read value of texture of current pixel
"vec4 value = texture2DRect(texture,texCoord);"
//Perform pattern matching
"if(value[0]==116){"
//Set the pixel to maximum value
"gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);}"
"else if(value[0]==114){"
"gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);}"
"else if(value[0]==111){"
"gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);}"
"else if(value[0]==106){"
"gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);}"
"else if(value[0]==97){"
"gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);}"
"else if(value[0]==110){"
"gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);}"
"else{"
//Set the pixel to zero
"gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);}"
"}"
};


My output should be have some values. But it always zeros when I read it out. I using the following method to read:



/*Read values back*/
/*Set the target framebuffer to read*/
glReadBuffer(GL_FRONT);

/*Read pixels from framebuffer to PBO*/ glReadPixels(0,0,size,noOfpacket,GL_RGBA,GL_UNSIGN ED_BYTE,(void*)0);
checkError("glReadPixels error!");
/*Map the PBO to process its data by CPU*/
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboread);
result = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
printf("Data in frame buffer:\n");
for (i=0;i<noOfpacket*size;i++)
printf("%d",result[i]);
printf("\n\n");
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB,0);


I am not sure where is the problem. So, I test my fragment.I change to this:



"void main(void){"
"gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);"
"}"


Or



"void main(void){"
"gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}"


Unfortunately, I still get zeros. Where is problem actually?

Alfonse Reinheart
04-06-2011, 09:49 PM
glReadBuffer(GL_FRONT);

Why are you reading from the front buffer? That's generally not a good idea.

However, since your image is ostensibly in the front buffer, what do you see in the window?

SagoO
04-06-2011, 11:06 PM
Why are you reading from the front buffer? That's generally not a good idea.

Shouldnt I read from there? By default, it should be GL_FRONT right? If not where should I read?



However, since your image is ostensibly in the front buffer, what do you see in the window?

I do not render on a window. But I read it out using glReadPixels. I get all zeros.

Alfonse Reinheart
04-06-2011, 11:33 PM
Shouldnt I read from there?

No. In general, unless you know what you're doing, you should never directly write to or read from the front buffer. You render to the back buffer, then make the appropriate platform-specific swap buffers call to display that rendered image to the user.

So you should be using a double-buffered pixel format.


I do not render on a window.

I'd be interested to know how you manage that feat, since at least WGL doesn't let you do that. If you mean you render to a minimized window (not the same thing as not having a window), that's even worse.

Though it would explain why you're not getting anything back.

See, OpenGL has this thing called the "pixel ownership test." A pixel fails the pixel ownership test if it is off-screen, being covered by another window, or otherwise non-viewable given the current state of the window. If the window is minimized, all of the pixels fail the pixel ownership test.

OpenGL will neither render to nor read from any pixels that fail the pixel ownership test. Technically, what the spec says is that reading from those pixels will return "undefined" values. Which means that they could contain anything. In practice, the values will not contain anything useful.

This is the principle reason why, if you're doing pixel readback or GPGPU or somesuch, you generally render to an off-screen render target (ie: FBO). When you render to an FBO, all pixels automatically pass the pixel ownership test.

In general, when you're just starting out with shaders and stuff, it's a good idea to render to something that you can see, so you can confirm what is being rendered. That's why people generally don't start directly with GPGPU.

SagoO
04-06-2011, 11:51 PM
Actually what I mean is offscreen rendering. But I confused between FBO and PBO. I mixed up these 2 stuff already.

Now I use PBO to upload my texture. So, I use PBO to read out from frame buffer as well. But I forgot that PBO cannot do that.

So, FBO is the only option to perform offscreen rendering?

Can I use PBO to upload then create a offscreen rendering on FBO?

mobeen
04-06-2011, 11:51 PM
Alfonse ur replies are very comprehensive. I do check all of your answers since there is so much to learn from them.

Alfonse Reinheart
04-07-2011, 12:24 AM
Oh, one more thing.

Unless your texture format is an integral format (http://www.opengl.org/wiki/Image_Format), the values it stores are floating-point numbers.

Therefore:


vec4 value = texture2DRect(texture,texCoord);

Your texture is either an integral format (any image format that ends in "I" or "UI") or it isn't. If it is, then this function will fail, because your sampler type is a floating-point sampler, which is not compatible with an integral texture.

If it isn't (and I'm guessing it's not), then you probably uploaded your values to a GL_RED8 texture or some similar 8-bit single channel format. In which case, your values will be interpreted as an integer encoding of a floating-point value on the range [0, 1]. So if the number you upload is "0", you get 0.0f from the texture function. If the number you upload is "114", then you will get 114/255, or 0.45. Which is not equal to 114.

Which means your code, as written, will never return anything other than 0.

Really, you're trying to do way too much all at once. Slow down. First, get the ability to draw to the screen working. Then draw to an FBO. Then the ability to read those values back. Then the ability to read textures (writing the value to the screen to confirm them). After you do all of that, then you'll be ready to implement your actual logic. That is, reading the texture value, performing some computations, and return a result.

But if you do it all at once, like you do here, then you have multiple problems that all show up at the same time, and it's harder to say what the problem is.


So, I use PBO to read out from frame buffer as well. But I forgot that PBO cannot do that.

No, you can read the regular framebuffer with PBOs. The problem is that your framebuffer (ie: window) is not on the screen. And therefore nothing can be rendered to it or read back from it.

If you brought your window on-screen (and rendered to the back buffer), you would probably get more reasonable results.


So, FBO is the only option to perform offscreen rendering?

It's either that or Pbuffers. If your hardware/drivers of choice supports FBOs, I'd suggest using them. They're much easier to manage overall.

SagoO
04-07-2011, 12:30 AM
Okay...I try to follow your step. Thanks for your reply. It is a very good information for me.

SagoO
04-07-2011, 01:35 AM
If I want to display my texture on screen, it does not necessary go through fragment right?

I just want to display it directly without process.

I read some tutorial how to draw a cube. But what to do if I want to display my texture?

Now, I already sent the data into the texture. So, I got the texture. But what to do next?

BionicBytes
04-07-2011, 03:09 AM
vec4 value = texture2DRect(texture,texCoord);

Don't forget that becuase you have chosen to use rectangular textures your texture coordinates are no longer from 0..1 but are now 0..width.
Remember this when you render an object using this texture.

SagoO
04-07-2011, 08:21 AM
Oh, one more thing.
Your texture is either an integral format (any image format that ends in "I" or "UI") or it isn't. If it is, then this function will fail, because your sampler type is a floating-point sampler, which is not compatible with an integral texture.

If it isn't (and I'm guessing it's not), then you probably uploaded your values to a GL_RED8 texture or some similar 8-bit single channel format. In which case, your values will be interpreted as an integer encoding of a floating-point value on the range [0, 1]. So if the number you upload is "0", you get 0.0f from the texture function. If the number you upload is "114", then you will get 114/255, or 0.45. Which is not equal to 114.


If I am using GL_UNSIGNED_BYTE of data, what format of texture should i use?

I want each pixel takes one value of my data only.

If I choose RGB, it will take three values of my data into one pixel.

This is a quite confusing part too. I keep trying different format until I can get my exact texture.

If I am using the wrong format, the value of the texture seems to appear all zeros only.

StefanG
04-07-2011, 09:35 AM
As Alfonse said, you really should do some texturing and shader tutorials and learn to walk before you run. We are happy to help, but your problems are many and concern things that are rather basic.

You should also be aware that for performance, conditionals (if-else) are about the worst statements you can put in a shader, in particular when they explode into many separate cases like your example, and when the conditions change often between "true" and "false" from one fragment to the next.

You shader code would be better off using an array for the color, but I really cannot tell what you are trying to accomplish, so I may be giving you the wrong advice here.