我可以在OpenGL中分解图像并将其绘制为三个或四个单独的2d基元

时间:2016-02-09 23:58:29

标签: c++ opengl

基本上我的OpenGL代码从2d纹理256 * 256图像读取并从其数据写入屏幕上的2d生成三角形

我的问题是未绘制或不可见的数据实际发生了什么,片段着色器是否访问了那些不会被绘制到屏幕的数据部分或是否完全避免了?

例如,对于三角形(或顶点)的尖端,它只是在三角形的尖端处获取该一个片段的信息,而忽略了正方形的剩余长度,或者它实际上是否经过了所有的线条。图像数据的长度(即256像素)并在其他地方打印等

它被丢弃了还是实际上是在三角形之外画到其他地方但是没有看到?

我可以实际访问此数据并将其绘制到另一个三角形或屏幕上的其他位置吗?这样我就可以在两个或三个基元上分解纹理图像

#include <stdio.h>
#include <stdlib.h>
//#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
//#include <X11/Xutil.h>
#include <GL/glew.h>
#include <GL/glx.h>
#include <time.h>
#include <math.h>


   const char* vertex_shader =
      "#version 400\n"
      "layout(location =  0) in vec2 vp;"
      "layout(location = 1) in vec2 tex;"
      "out vec2 texCoord;"
      "void main () {"
      "  gl_Position = vec4 (vp, 0.0f, 1.0f);"
      "  texCoord = tex; "
      "}";

   const char* fragment_shader =
      "#version 400\n"
      "uniform sampler2D s;"
      "in vec2 texCoord;"
      "out vec4 color;"
      "void main () {"
      "color = texture(s, texCoord);"
      "}";

   static int att[] =
   {
      GLX_X_RENDERABLE    , True,
      GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
      GLX_RENDER_TYPE     , GLX_RGBA_BIT,
      GLX_X_VISUAL_TYPE   , GLX_TRUE_COLOR,
      GLX_RED_SIZE        , 8,
      GLX_GREEN_SIZE      , 8,
      GLX_BLUE_SIZE       , 8,
      GLX_ALPHA_SIZE      , 8,
      GLX_DEPTH_SIZE      , 24,
      GLX_STENCIL_SIZE    , 8,
      GLX_DOUBLEBUFFER    , True,
      //GLX_SAMPLE_BUFFERS  , 1,
      //GLX_SAMPLES         , 4,
      None
   };

   Display                           *dpy;
   Window                            root;   
   XVisualInfo                      *vi;
   Colormap                          cmap;
   XSetWindowAttributes       swa;
   Window                            win;
   GLXContext                      context;
   GLXFBConfig                   *fbc;
   GLXWindow                     glxWin; 


   GLuint vs;
   GLuint fs;
   GLuint shader_program;

unsigned char * loadData(){
   unsigned char header[54];

   unsigned int width=256, height=256;
   unsigned int imageSize = width*height * 3; 

   unsigned char * data = (unsigned char *)malloc(imageSize);


   FILE *file = fopen("256x256.bmp", "rb");
      if(!file){printf("Failed to open\n"); return 0;}

   fread(header, 1, 54, file);

   fread(data, 1, imageSize, file );

   fclose(file);

   return data;
}   

void createShaders(){

   GLint result;
   GLsizei log_length;
   GLchar data[255]; 
   GLchar data2[255];

   vs = glCreateShader (GL_VERTEX_SHADER);
   glShaderSource (vs, 1, &vertex_shader, NULL);
   glCompileShader (vs);

   glGetShaderiv(vs, GL_COMPILE_STATUS,&result);
   if(result == GL_FALSE){ 
      glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &log_length);  
      glGetShaderInfoLog(vs, log_length, NULL, data );
      printf("vertex shader %s\n", data);
   }

   fs = glCreateShader (GL_FRAGMENT_SHADER);
   glShaderSource (fs, 1, &fragment_shader, NULL);
   glCompileShader (fs);

   glGetShaderiv(fs, GL_COMPILE_STATUS,&result);
   if(result == GL_FALSE){
      glGetShaderiv(fs, GL_INFO_LOG_LENGTH, &log_length);   
      glGetShaderInfoLog(fs, log_length, NULL, data2 );
      printf("fragment shader %s\n", data2);
   }

   shader_program = glCreateProgram ();
   glAttachShader (shader_program, fs);
   glAttachShader (shader_program, vs);
   glLinkProgram (shader_program);

   glUseProgram (shader_program);


}

void init(){


   dpy = XOpenDisplay(NULL);

   int                            fbcount;

   if (!dpy){
      printf("Failed to open X display\n");
      exit(1);
   }   

   root = DefaultRootWindow(dpy);

   //request a framebuffer configuration
   fbc = glXChooseFBConfig(dpy, DefaultScreen(dpy), att, &fbcount);

   if (!fbc){
      printf( "Failed to retrieve a framebuffer config\n" );
      exit(1);
   }

   vi = glXGetVisualFromFBConfig( dpy, fbc[0] );

   if(vi==NULL){
      printf("Error getting visual info\n");
      exit(1);
   }
   swa.colormap = XCreateColormap( dpy, RootWindow( dpy, vi->screen ), vi->visual, AllocNone );

   swa.background_pixmap = None ;
   swa.border_pixel            = 0;
   swa.event_mask            = StructureNotifyMask;

   //Window XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valuemask, attributes) 

   win = XCreateWindow( dpy, RootWindow( dpy, vi->screen ), 0, 0, 640, 480, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa );
   if ( !win ){
      printf( "Failed to create window.\n" );
      exit(1);
   }

   context = glXCreateNewContext( dpy, fbc[0], GLX_RGBA_TYPE, NULL, True );

   glxWin = glXCreateWindow(dpy, fbc[0], win, NULL);

   XMapWindow(dpy, win);

   glXMakeContextCurrent(dpy, glxWin, glxWin, context);

   // start GLEW extension handler
   glewExperimental = GL_TRUE;
   GLuint err = glewInit();

   if(err!=GLEW_OK){
      fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
      exit(1);
   }

    XSelectInput(dpy, win, ButtonPressMask|KeyPressMask);

   // tell GL to only draw onto a pixel if the shape is closer to the viewer
   //glEnable (GL_DEPTH_TEST); // enable depth-testing
   //glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer"


}

int main(){

   init();
   createShaders();

   unsigned char * data = loadData();

   GLuint tex;
   glGenTextures(1, &tex);

   glBindTexture(GL_TEXTURE_2D, tex);

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_BGR,
              GL_UNSIGNED_BYTE, data);

   GLuint vbo;
   GLuint vao;

   float s = 256.0/640.0, r =256.0/480.0 ;

   int k = 1;

   glGenVertexArrays(1, &vao);
   glBindVertexArray(vao);

   GLfloat vertices[] = 
     // x      y     U    V
   {-1.0*s, -1.0*r, 0.0, 0.0,
     0.0*s, 1.0*r, 0.5, 1.0,
     1.0*s,  -1.0*r, 1.0, 0.0};
   // -1.0*s/k,  1.0*r/k, 0.0, 1.0 };

   glGenBuffers(1, &vbo);
   glBindBuffer(GL_ARRAY_BUFFER, vbo);
   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
   glEnableVertexAttribArray(0);

   glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (const GLvoid*)(2 * sizeof(GLfloat)));
   glEnableVertexAttribArray(1);

   //glPointSize(40.0f);

   glDrawArrays(GL_TRIANGLES, 0, 3);


   glXSwapBuffers ( dpy, glxWin );
   sleep(6);


   //////////////de-initialize
   free(data);
   glXMakeContextCurrent( dpy, 0, 0, NULL );
   glXDestroyContext( dpy, context );
   glXDestroyWindow(dpy, glxWin);
   XDestroyWindow( dpy, win );
   XCloseDisplay( dpy );

   return 0;
}

所以上面是我的代码,它正确渲染并生成一个简单的2D图像渲染,256 * 256到屏幕上的三角形

2 个答案:

答案 0 :(得分:0)

您提供给几何体的UV定义了纹理的哪些部分被绘制。完全取决于硬件来定义纹理如何贴在几何体上,这就是我不会评论的原因:

  

它被丢弃了还是实际上是在三角形之外画到其他地方但是没有看到?

但是,您可以假设驱动程序在您给出的UV上进行插值,根据几何体的哪个部分映射到当前正在绘制的屏幕像素,并确定纹理的哪个部分需要被使用并应用于屏幕像素。换句话说,它只会使用纹理中实际上在几何体上的部分。

如果要将此纹理绘制到其他几何体上,则应在绘制这些纹理时为其绑定,并为它们提供正确的UV。

答案 1 :(得分:0)

在大多数硬件上,图形渲染芯片在帧缓冲区边界(或剪切区域)处剪切三角形。帧缓冲区外的几何和片段在渲染时尽早被丢弃。

不会在缓冲区外为这些片段调用片段着色器。