PDA

View Full Version : GL_TEXTURE_RECTANGLE with GLuint data?



PrestoChung
01-25-2011, 03:34 AM
No matter what values i fill my data with, the texture is drawn black. Since it is being drawn to the screen, I use the screen coordinates as texel coordinates in the shader.
<div class="ubbcode-block"><div class="ubbcode-header">Click to reveal.. <input type="button" class="form-button" value="Show me!" onclick="toggle_spoiler(this, 'Yikes, my eyes!', 'Show me!')" />]<div style="display: none;">

static const Uint32 MAX_UINT32 = 0xFFFFFFFF;
void CreateTexture(){
Uint32 lsize = SCREEN_WIDTH*SCREEN_HEIGHT*4;
GLuint* ldata = new GLuint[lsize];
for( Uint32 i=0; i<lsize; ++i ){
if( (i+1)%4 ){
ldata[i]=0; //black
}
else{
ldata[i]=MAX_UINT32; //alpha
}
}
//white pixel in center of screen
ldata[lsize/2+(Uint32)HALF_W] = MAX_UINT32;
ldata[lsize/2+(Uint32)HALF_W+1] = MAX_UINT32;
ldata[lsize/2+(Uint32)HALF_W+2] = MAX_UINT32;

glActiveTexture( GL_TEXTURE0 );

glGenTextures( 1, &amp;mTexId );
glBindTexture( GL_TEXTURE_RECTANGLE, mTexId );
glTexImage2D( GL_TEXTURE_RECTANGLE, 0, GL_RGBA,
SCREEN_WIDTH, SCREEN_HEIGHT, 0,
GL_RGBA, GL_UNSIGNED_INT, ldata );
delete[] ldata;
}[/QUOTE]</div>

No white pixels show up, even if I initialize all the data to MAX_UINT32

mobeen
01-25-2011, 04:04 AM
Try this


Uint32 lsize = SCREEN_WIDTH*SCREEN_HEIGHT*4;
Uint32 HALF_W = SCREEN_WIDTH>>1;
Uint32 HALF_H = SCREEN_HEIGHT>>1;
GLuint* ldata = new GLuint[lsize];
for( Uint32 i=0; i<lsize; ++i ){
if( (i+1)%4 ){
ldata[i]=0; //black
}
else{
ldata[i]=MAX_UINT32; //alpha
}
}
//white pixel in center of screen
ldata[(SCREEN_WIDTH*HALF_W+ HALF_H)*4] = MAX_UINT32;
ldata[(SCREEN_WIDTH*HALF_W+ HALF_H)*4+1] = MAX_UINT32;
ldata[(SCREEN_WIDTH*HALF_W+ HALF_H)*4+2] = MAX_UINT32;
glActiveTexture( GL_TEXTURE0 );
glGenTextures( 1, &amp;mTexId );
glBindTexture( GL_TEXTURE_RECTANGLE, mTexId );
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D( GL_TEXTURE_RECTANGLE, 0, GL_RGBA, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT, ldata );
delete[] ldata;

Also make sure that the texture coordinates you assign to the geometry are not normalized like this,


glBegin(GL_QUADS);
glTexCoord2f(0,0);glVertex2i(0,0);
glTexCoord2f(SCREEN_WIDTH,0);glVertex2i(SCREEN_WID TH,0);
glTexCoord2f(SCREEN_WIDTH,SCREEN_HEIGHT);glVertex2 i(SCREEN_WIDTH,SCREEN_HEIGHT);
glTexCoord2f(0,SCREEN_HEIGHT);glVertex2i(0,SCREEN_ HEIGHT);
glEnd();

PrestoChung
01-25-2011, 03:33 PM
Still can't get anything but black pixels to draw. And yes, since the texel coords and screen coords co-incide, I am just passing on the texture coordinates like so out vec2 texPos = inVertex.xy

Isn't MAX_UINT32 supposed to be white for a texture specified with
GL_UNSIGNED_INT as the type? Even if I fill my data with all MAX_UINT32 values, it still draws black.

mobeen
01-25-2011, 04:50 PM
Isn't MAX_UINT32 supposed to be white for a texture specified with
GL_UNSIGNED_INT as the type? Even if I fill my data with all MAX_UINT32 values, it still draws black.
Well i get this output which is exactly what I should get.
Could u try this minimal glut code and tell me what u get?


#include <gl/glew.h>
#include <gl/glut.h>
typedef unsigned int Uint32;
static const Uint32 SCREEN_WIDTH = 800;
static const Uint32 SCREEN_HEIGHT = 600;
static const Uint32 MAX_UINT32 = 0xFFFFFFFF;
int HALF_W = SCREEN_WIDTH>>1;
int HALF_H = SCREEN_HEIGHT>>1;
GLuint txt;
unsigned char* bitmapData;
void Render()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glTexCoord2i(0,0);glVertex2i(0,0);
glTexCoord2i(SCREEN_WIDTH,0);glVertex2i(SCREEN_WID TH,0);
glTexCoord2i(SCREEN_WIDTH,SCREEN_HEIGHT);glVertex2 i(SCREEN_WIDTH,SCREEN_HEIGHT);
glTexCoord2i(0,SCREEN_HEIGHT);glVertex2i(0,SCREEN_ HEIGHT);
glEnd();

glFinish();
glutSwapBuffers();
}
void CreateTexture(GLuint* texID){
Uint32 lsize = SCREEN_WIDTH*SCREEN_HEIGHT*4 ;
GLuint* ldata = new GLuint[lsize ];
memset(ldata,0,lsize );
for( Uint32 i=0; i<lsize; ++i ){
if( (i+1)%4 ){
ldata[i]=0; //black
}else{
ldata[i]=MAX_UINT32; //alpha
}
}
//white pixel in center of screen
ldata[(SCREEN_WIDTH*HALF_H+ HALF_W)*4] = MAX_UINT32;
ldata[(SCREEN_WIDTH*HALF_H+ HALF_W)*4+1] = MAX_UINT32;
ldata[(SCREEN_WIDTH*HALF_H+ HALF_W)*4+2] = MAX_UINT32;

glActiveTexture( GL_TEXTURE0 );
glGenTextures( 1, texID );
glBindTexture( GL_TEXTURE_RECTANGLE, *texID );
glTexParameterf(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D( GL_TEXTURE_RECTANGLE, 0, GL_RGBA, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT, ldata );
delete[] ldata;
}


int main(int argc, char** argv)
{
glutInit(&amp;argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
glutInitWindowSize(SCREEN_WIDTH,SCREEN_HEIGHT);
glutCreateWindow("SIMPLE DISPLAY");
glewInit();
glutDisplayFunc(Render);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,SCREEN_WIDTH, 0, SCREEN_HEIGHT);

glEnable(GL_TEXTURE_RECTANGLE);
CreateTexture(&amp;txt);
glutMainLoop();
return 0;
}

This should give u this output. There is a small white dot in the center.
http://www3.ntu.edu.sg/home2007/mova0002/test/output.png

PrestoChung
01-25-2011, 08:49 PM
I think it's because I'm using sampler2D but I need samplerRECT

Is this not core functionality in a 3.3 context? How hard would it be to add?

Alfonse Reinheart
01-25-2011, 08:52 PM
I think it's because I'm using sampler2D but I need samplerRECT

And that's why it's a good idea to post your shader.


Is this not core functionality in a 3.3 context? How hard would it be to add?

You just use a samplerRect in your shader instead of a sampler2d.

PrestoChung
01-25-2011, 09:00 PM
Okay I found that I can use a usampler2DRect,
but there does not seem to be defined a texture2DRect( , );, I get the shader compiler error C7531: "global function texture2DRect requires "#extension GL_EXT_gpu_shader4 : enable" before use

is this a line I can add to my code somewhere? or do I need some header files?

Edit: I got it, just add #extension GL_EXT_gpu_shader4 : enable to my shader now it all works :)

PrestoChung
01-25-2011, 10:51 PM
Is GL_TEXTURE_RECTANGLE not compatible with glCopyTexImage2D? I wanted to copy the last frame into this texture but it would complicate things if the texture has to be a power of 2 instead of the screen dimensions.

mobeen
01-25-2011, 10:54 PM
Is GL_TEXTURE_RECTANGLE not compatible with glCopyTexImage2D? I wanted to copy the last frame into this texture but it would complicate things if the texture has to be a power of 2 instead of the screen dimensions.
glCopyTexImage2D should work fine with GL_TEXTURE_RECTANGLE. You should check your code. The first thing i would look at is my texture format and the internal format I am passing to glCopyTexImage2D.

PrestoChung
01-25-2011, 11:40 PM
<div class="ubbcode-block"><div class="ubbcode-header">Click to reveal.. <input type="button" class="form-button" value="Show me!" onclick="toggle_spoiler(this, 'Yikes, my eyes!', 'Show me!')" />]<div style="display: none;">
#version 330
#extension GL_EXT_gpu_shader4 : enable

uniform usampler2DRect tex;

in vec2 texPos;

out vec4 outFragColor;

void main()
{
vec4 out_color;
vec4 tex_color_left;

vec2 top = vec2(0, 1);
vec2 bottom = vec2(0, -1);
vec2 right = vec2(1, 0);
vec2 left = vec2(-1, 0);

tex_color_left = texture(tex, texPos+left);

if( tex_color_left.x>0.5 ){
out_color = vec4(1.0, 1.0, 1.0, 1.0);
}
else{
out_color = vec4(0.0, 0.0, 0.0, 1.0);
}

outFragColor = out_color;
}[/QUOTE]</div>

Edit: ah, i answered my own question again :) (problem with equality with floats)

Alfonse Reinheart
01-25-2011, 11:51 PM
Edit: I got it, just add #extension GL_EXT_gpu_shader4 : enable to my shader now it all works

You're already defining GLSL version 3.30. So you have access to GLSL 3.30. You shouldn't be using functions like "texture2D" and so forth. The preferred functions don't mention the sampler type at all, because they're all overloaded for the appropriate sampler type. The function you're really looking for is "texture".

mobeen
01-25-2011, 11:53 PM
Are you writing to the same buffer from where u r reading the data?

PrestoChung
01-25-2011, 11:59 PM
I got that sorted, the program just didn't like when I checked for tex_color_left.x==1.0, so I changed it to tex_color_left.x>0.5 and that works.

However, when the white pixel gets to the right side of the screen, it doesn't wrap around. I read in the spec that GL_TEXTURE_WRAP_R, S, T should default to repeat. So I have added the glTexParameteri( ... , GL_REPEAT ); call to enable repeat but still it does not loop around

PrestoChung
01-26-2011, 12:04 AM
I just have a Texture bound to GL_TEXTURE_RECTANGLE. I read from this texture and draw to the current buffer. After I'm done drawing to the current buffer, before I swap I call glCopyTexImage2D( ); Well, you can see the loop here
Uint32 len = 500;
for( Uint32 i=0; i<len; ++i ){
glClear( GL_COLOR_BUFFER_BIT );
myOnscreen.Draw();
glCopyTexImage2D( GL_TEXTURE_RECTANGLE, 0, GL_RGBA,
0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0 );
SDL_GL_SwapWindow( mMainWindow );
}

mobeen
01-26-2011, 12:13 AM
Could u issue a glFlush() or glFinish() after the glCopyTexImage call and before your SDL_GL_SwapWindow call.
And why do u need to render 500 times issuing a texture copy in each iteration?
You could render to an FBO directly which would save u these 500 copies.

PrestoChung
01-26-2011, 12:24 AM
I don't have any experience with FBO.

However I don't think I want to do that in this case: I can't make changes to the underlying Texture until all of the pixels for the current frame have been processed (as their color depends on the neighboring pixels). If I was rendering into the original texture, I would be losing information that I need to update adjacent pixels.

Performance right now doesn't seem to be a problem.

PrestoChung
01-26-2011, 12:34 AM
According to this thread (http://www.gamedev.net/topic/517175-wordaround-for-gl_texture_rectangle_arb-gl_repeat-issue/) GL_TEXTURE_RECTANGLE doesn't support GL_REPEAT?

If so, it would make things very inconvenient. I suppose I would have to define a uniform float to store a normalized 'pixel' size ( 1/SCREEN_W and 1/SCREEN_H ) if I wanted to do adjecent pixel access?

ZbuffeR
01-26-2011, 12:45 AM
Indeed, texture rectangle have lots of limitations, compared to normal 2D non-power-of-two textures.
Any reason you use RECTANGLE instead of NPOT textures ?

PrestoChung
01-26-2011, 12:46 AM
I was under the assumption that TEXTURE_2D was a power of two texture

I also wanted to keep coincidence with screen and texture coordinates so I could keep things more simple. It's a full-screen cellular automata. seems with normalized coordinates it would get messy for a discrete math problem

Alfonse Reinheart
01-26-2011, 01:37 AM
You really need to read the GLSL 3.30 specification. Because you can access anything with "texelFetch," which doesn't use normalized texture coordinates. And you can get the size of a texture with the "textureSize" function. And OpenGL has supported NPOTs since GL 2.0. So there's no need for you to use a rectangle texture here.

If the spec is too big, you could try reading the abridged version (http://www.opengl.org/wiki/GLSL_Sampler).

PrestoChung
01-26-2011, 02:45 AM
You really need to read the GLSL 3.30 specification. Because you can access anything with "texelFetch," which doesn't use normalized texture coordinates. And you can get the size of a texture with the "textureSize" function. And OpenGL has supported NPOTs since GL 2.0. So there's no need for you to use a rectangle texture here.

If the spec is too big, you could try reading the abridged version (http://www.opengl.org/wiki/GLSL_Sampler).

Is this the spec you are referring to? http://www.opengl.org/registry/doc/GLSLangSpec.3.30.6.pdf
I couldn't find any reference to texelFetch in it by searching

ZbuffeR
01-26-2011, 03:03 AM
That is why he put a second link ...
http://www.opengl.org/wiki/GLSL_Sampler#Direct_texel_fetches

PrestoChung
01-26-2011, 03:12 AM
Thanks I saw that. Unfortunately from what I read here (http://www.farrarfocus.com/atom/081230.htm), texelFetch doesn't support wrap either :\

mobeen
01-26-2011, 06:22 AM
I think you can do wrapping in shader using something like this,


vec4 leftVal=texture(texturemap, mod(uv.st+vec2(-1,0), textureSize()));
vec4 rightVal=texture(texturemap, mod(uv.st+vec2(1,0), textureSize()));
vec4 topVal=texture(texturemap, mod(uv.st+vec2(0,-1), textureSize()));
vec4 rightVal=texture(texturemap, mod(uv.st+vec2(0,1), textureSize()));

I am not sure if this works but u can try.

PrestoChung
01-28-2011, 04:34 AM
I think you can do wrapping in shader using something like this,


vec4 leftVal=texture(texturemap, mod(uv.st+vec2(-1,0), textureSize()));
vec4 rightVal=texture(texturemap, mod(uv.st+vec2(1,0), textureSize()));
vec4 topVal=texture(texturemap, mod(uv.st+vec2(0,-1), textureSize()));
vec4 rightVal=texture(texturemap, mod(uv.st+vec2(0,1), textureSize()));

I am not sure if this works but u can try.

I ended up doing this. It seems to work correctly, maybe some sort of problem with wrapping on the bottom edge but this was just a quick exercise anyway so I'm happy with it :)

Thanks all for the help on this one. Here's a few vids of the results
1 (http://www.youtube.com/watch?v=ipVrCNJgNiU)
2 (http://www.youtube.com/watch?v=F5kRq5TwEkU)
3 (http://www.youtube.com/watch?v=c9_UoK76mes)