1
votes

Ive been looking through the internet for a while now trying to find out if i can DIRECTLY manipulate Pixels like those that makes up the triangle in a mesh not vertex co-ordinates.

When a mesh is being formed in OpenGL the vertex co-ordinates that forms independent triangles are each filled with Pixels that gives it color.

Those pixels are what im trying to manipulate. So far in every Tutorial all i'm seeing is how to alter vertex coords even in the Fragment shader parts of Glsl tutorials i'm not finding anything on the Pixels directly. I'm being shown Texture and Vertex co-ordinates no direct Pixel manipulation.

So far what i know happens is each vertex is assigned some color value and all the Pixel processes get done during execution and you see the results.

So can Pixels be directly altered in OpenGl for each Triangle or What would u guys recommend? Cuz i've heard it might be possible in OpenCV but thats stuff is about Textures

1
You can make a point and remap the viewspace into pixels, but it is not supported well, and will likely be slow. What are you trying to achieve? - Neil
Hi Neil. I'm trying to create a normal map programatically through C++ OpenGl but to do that i would first of all need to at least be able store the RGB values of each pixel in a complex Mesh that is directly below a triangle from a low poly Mesh and that fall in the parameters of that low Poly Mesh triangle's vertex positions. From there i will have to do more research and even later still apply something called a TBN matrix. But i need to be able to Manage Pixels before i can do anything else. - Gore District
Hmm, like copy your OpenGL to a file instead of the screen? That's definitely possible. But I don't think you want that. A normal map is just a texture, where RGB is used for XYZ. Editing textures is out of OpenGL's purview, but if they are uncompressed, you can edit them directly. It depends also on your pixel format. - Neil
You could try a PBO (pixel buffer object). Though you will need to draw it as you would any other texture, you can at least access the texture pretty freely (there is a significant performance penalty to this depending how you use it, bear that in mind) - Anne Quinn
It sounds like you want to do a pixel transfer using glReadPixels. It also sounds like you'll be generating the normal map once (and then reusing that normal map many times), so performance is less of an issue. - Yun

1 Answers

0
votes

If I get it right you have high poly mesh and want to simplify it by creating normal map for smaller poly count faces ...

Never done this but I would attack this problem like this:

  1. create UV mapping of high poly mesh

  2. create low poly mesh

    so you need to merge smaller adjacent faces into bigger ones. Merging only faces that are not too angled to starting face (abs dot between normals is smaller than threshold)... You also need to remember original mesh of merged face.

  3. for each merged face render normal

    so render the merged face original polygon to texture but use UV as 2D vertex coordinates and output actual triangle normal as color

    This will copy the normals into normal map at the correct position. Do not use any depth buffering blending lighting or whatever. Also the 2D view must be scaled and translated so the UV mapping will cover your texture (no perspective) Do not forget that the normal map (if RGB float used) is clamped so you should first normalize the normal and then convert to range <0,1> for example:

    n = 0.5 * (vec3(1.0,1.0,1.0) + normalize(n));
    
  4. read back the rendered texture

    now it should hold the whole normal map. In case you do not have Render to texture available (older Intel HD) you can render to screen instead and then just use glReadPixels.

    As you want to save this to image here a small VCL example of saving to 24 bit bmp:

     //---------------------------------------------------------------------------
     void screenshot(int xs,int ys)          // xs,ys is GL screen resolution
         {
         // just in case your environment does not know basic programing datatypes
         typedef unsigned __int8  BYTE;
         typedef unsigned __int16 WORD;
         typedef unsigned __int32 DWORD;
    
         xs&=0xFFFFFFFC;                     // crop down resolution to be divisible by 4
         ys&=0xFFFFFFFC;                     // in order make glReadPixel not crashing on some implementations
    
         BYTE *dat,zero[4]={0,0,0,0};
         int hnd,x,y,a,align,xs3=3*xs;
    
         // allocate memory for pixel data
         dat=new BYTE[xs3*ys];
         if (dat==NULL) return;
    
         // copy GL screen to dat
         glReadPixels(0,0,xs,ys,GL_BGR,GL_UNSIGNED_BYTE,dat);
         glFinish();
    
    
         // BMP header structure
         #pragma pack(push,1)
         struct _hdr
             {
             char ID[2];
             DWORD size;
             WORD  reserved1[2];
             DWORD offset;
             DWORD reserved2;
             DWORD  width,height;
             WORD  planes;
             WORD  bits;
             DWORD compression;
             DWORD imagesize;
             DWORD xresolution,yresolution;
             DWORD ncolors;
             DWORD importantcolors;
             } hdr;
         #pragma pack(pop)
    
         // BMP header extracted from uncompressed 24 bit BMP
         const BYTE bmp24[sizeof(hdr)]={0x42,0x4D,0xE6,0x71,0xB,0x0,0x0,0x0,0x0,0x0,0x36,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0xF4,0x1,0x0,0x0,0xF4,0x1,0x0,0x0,0x1,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0xB0,0x71,0xB,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
    
         // init hdr with 24 bit BMP header
         for (x=0;x<sizeof(hdr);x++) ((BYTE*)(&hdr))[x]=bmp24[x];
    
         // update hdr stuf with our image properties
         align=0;    // (4-(xs3&3))&3;
         hdr.size=sizeof(hdr)+(ys*(xs3+align));
         hdr.width=xs;
         hdr.height=ys;
         hdr.imagesize=ys*xs3;
    
         // save BMP file (using VCL file functions exchange them with whatever you got)
         hnd=FileCreate("screenshot.bmp");   // create screenshot image file (binary)
         if (hnd!=-1)                        // if file created
             {
             FileWrite(hnd,&hdr,sizeof(hdr));// write bmp header
             for (a=0,y=0;y<ys;y++,a+=xs3)   // loop through all scan lines
                 {
                 FileWrite(hnd,&dat[a],xs3); // write scan line pixel data
                 if (align)                  // write scan line align zeropad if needed
                  FileWrite(hnd,zero,align);
                 }
             FileClose(hnd);                 // close file
             }
    
         // cleanup before exit
         delete[] dat;                       // release dat
         }
     //---------------------------------------------------------------------------
    

    The only thing used from VCL are binary file access routines so just swap them with what you have at disposal. Now you can open this bmp in whatever image software and convert to whatever format you want like png... without the need to encode it yourself.

    The bmp header structure was taken from this QA:

    Also beware of using char/int instead of BYTE/WORD/DWORD it usually leads to data corruption for tasks like this if you do not know what you doing...

You can do the same with color if the mesh is textured ... That way the normal map and color map would have the same UV mapping even if the original mesh uses more than single texture ...