c++ - GLSL 4.3 纹理问题

标签 c++ opengl glsl x11

我无法让我的纹理正常工作。下面是我的代码

static const char * codeVertexShade = "\
#version 430\n\
  attribute vec2 texCoor;\
  out vec2 texOut;\
  void main(){\
    gl_Position = ftransform();\
    texOut.x = texCoor.x; texOut.y = texCoor.y;\
  }\
";

static const char * codeFragmentShade = "\
#version 430\n\
  in vec4 col;\
  in vec2 texOut;\
  uniform sampler2D sampTex;\
  void main(){\
    gl_FragColor = texture(sampTex, texOut);\
  }\
";

#define CHECKGL if(!checkGL(__LINE__)){ throw std::exception(); }

bool checkGL(unsigned int line){
  switch(glGetError()){
  case GL_NO_ERROR:
    return true;
  case GL_INVALID_ENUM:
    std::cout<< "GL_INVALID_ENUM " << line << std::endl;
    break;
  case GL_INVALID_VALUE:
    std::cout<< "GL_INVALID_VALUE " << line << std::endl;
    break;
  case GL_INVALID_OPERATION:
    std::cout<< "GL_INVALID_OPERATION " << line << std::endl;
    break;
  case GL_INVALID_FRAMEBUFFER_OPERATION:
    std::cout<< "GL_INVALID_FRAMEBUFFER_OPERATION " << line << std::endl;
    break;
  case GL_OUT_OF_MEMORY:
    std::cout<< "GL_OUT_OF_MEMORY " << line << std::endl;
    break;
  }

  return false;
}

GLint createShader(const char *pCode, GLenum type){
  GLint id = glCreateShader(type);

  const char * arrCode[1] = { pCode };

  glShaderSource(id, 1, arrCode, NULL);
  glCompileShader(id);

  GLint status=0;
  glGetShaderiv(id, GL_COMPILE_STATUS, &status);
  if(status != GL_TRUE){
    GLchar info[1024];
    glGetShaderInfoLog(id, 1024, NULL, info);
    std::cout << info << std::endl;
    throw std::exception();
  }

  return id;
}

int main(void)
{
  testDeath die;

  try{
    int NumberOfExtensions=0;

    glGetIntegerv(GL_NUM_EXTENSIONS, &NumberOfExtensions);
    for(int i=0; i<NumberOfExtensions; i++) {
      const GLubyte *ccc=glGetStringi(GL_EXTENSIONS, i);
      std::cout << (const char*)ccc << std::endl;
    }

    int attrListDoubleBuff[] = {
      GLX_RGBA, GLX_DOUBLEBUFFER,
      None
    };

    int attrListSingleBuff[] = {
      GLX_RGBA,
      None
    };

    Bool    mDoubleBuffered;
    XEvent  mEvent;
    Atom    mDeleteMessage;

    Display *mDisplay = XOpenDisplay(0);
    int mScreen = DefaultScreen(mDisplay);
    XVisualInfo *vi = glXChooseVisual(mDisplay, mScreen, attrListDoubleBuff);

    if(vi == NULL){
      vi = glXChooseVisual(mDisplay, mScreen, attrListSingleBuff);
      mDoubleBuffered = False;
    }else{
      mDoubleBuffered = True;
    }

    GLXContext mContext = glXCreateContext(mDisplay, vi, 0, GL_TRUE);
    Colormap cmap = XCreateColormap(
      mDisplay,
      RootWindow(mDisplay, vi->screen),
      vi->visual,
      AllocNone
    );

    XSetWindowAttributes mWinAttr;
    mWinAttr.colormap = cmap;
    mWinAttr.border_pixel = 0;
    mWinAttr.event_mask = KeyPressMask | ButtonPressMask | StructureNotifyMask;

    Window mWindow = XCreateWindow(
      mDisplay,
      RootWindow(mDisplay, vi->screen),
      50, 50,
      200, 200,
      0,
      vi->depth,
      InputOutput,
      vi->visual,
      CWBorderPixel | CWColormap | CWEventMask,
      &mWinAttr
    );

    mDeleteMessage = XInternAtom(mDisplay, "WM_DELETE_WINDOW", True);
    XSetWMProtocols(mDisplay, mWindow, &mDeleteMessage, 1);

    XSetStandardProperties(
      mDisplay,
      mWindow,
      "test",
      "test",
      None,
      NULL,
      0,
      NULL
    );

    XMapRaised(mDisplay, mWindow);
    XFlush(mDisplay);
    glXMakeCurrent(mDisplay, mWindow, mContext);

    {
      const char* version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
      const char* vglsl = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
      std::cout  << "Version 1: " << std::endl
      << "OpenGL=" << (version == NULL ? "error" : version) << std::endl
      << "GLSL=" << (vglsl == NULL ? "error" : vglsl) << std::endl
      ;
    }

    glEnableClientState(GL_VERTEX_ARRAY);

    GLuint idShadeMain = glCreateProgram();
    if(idShadeMain==0){
      std::cout << "Shader program not made" << std::endl;
      throw std::exception();
    }

    GLint idVertShade = createShader(codeVertexShade, GL_VERTEX_SHADER);
    GLint idFragShade = createShader(codeFragmentShade, GL_FRAGMENT_SHADER);

    glAttachShader(idShadeMain, idVertShade);
    glAttachShader(idShadeMain, idFragShade);

    const GLfloat vbuff[]={
      -0.8,   0.8,  0,
       0.8,   0.8,  0,
       0.8,  -0.8,  0,
      -0.8,  -0.8,  0
    };

    const GLint ibuff[]={
      0, 1, 2,
      2, 3, 0
    };

    const GLfloat tbuff[]={
    //  au    av    bu    bv    cu    cv
      0.0f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
      0.0f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f
    };

    enum vertAtt{
      vertAtt_verts = 0,
      vertAtt_texcoor,
      vertAtt_MAX
    };

    GLuint bufferIDs[vertAtt_MAX];
    glGenBuffers(vertAtt_MAX, bufferIDs);

    glBindBuffer(GL_ARRAY_BUFFER, bufferIDs[vertAtt_verts]); CHECKGL;
    glEnableVertexAttribArray(vertAtt_verts); CHECKGL;
    glVertexAttribPointer(vertAtt_verts, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glBufferData(
      GL_ARRAY_BUFFER,
      sizeof(vbuff),
      vbuff,
      GL_STATIC_DRAW
    );  CHECKGL;

    glBindBuffer(GL_ARRAY_BUFFER, bufferIDs[vertAtt_texcoor]); CHECKGL;
    glBindAttribLocation(idShadeMain, vertAtt_texcoor, "texCoor"); CHECKGL;
    glEnableVertexAttribArray(vertAtt_texcoor); CHECKGL;
    glVertexAttribPointer(vertAtt_texcoor, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glBufferData(
      GL_ARRAY_BUFFER,
      sizeof(tbuff),
      tbuff,
      GL_STATIC_DRAW
    );  CHECKGL;

    GLuint buffidIndexs;
    glGenBuffers(1, &buffidIndexs);    // Generate 1 index buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffidIndexs);
    glBufferData(
      GL_ELEMENT_ARRAY_BUFFER,
      sizeof(ibuff),
      ibuff,
      GL_STATIC_DRAW
    ); CHECKGL;

    GLuint idTex;
    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &idTex);
    if(glIsTexture(idTex)){
      std::cout << "Not Texture" << std::endl;
      throw std::exception();
    }
    glBindTexture(GL_TEXTURE_2D, idTex); CHECKGL;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    GLbyte buffTex[32*32*4]; memset(buffTex, 150, 32*32*4);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffTex); CHECKGL;

    glBindTexture(GL_TEXTURE_2D, 0);

    {
      GLint status = 0;
      GLchar log[1024] = { 0 };

      glLinkProgram(idShadeMain);
      glGetProgramiv(idShadeMain, GL_LINK_STATUS, &status);
      if(status != GL_TRUE){
        glGetProgramInfoLog(idShadeMain, 1024, NULL, log);
        std::cout << log << std::endl;
        throw std::exception();
    }

    GLint idSample = glGetUniformLocation(idShadeMain, "sampTex"); CHECKGL;
    if(idSample == -1){
      std::cout<<"Bad sample"<<std::endl;
      throw std::exception();
    }

    const char* DestroyWindowAtomName = "WM_PROTOCOLS";
    const size_t AtomNameLen = strlen(DestroyWindowAtomName);

    GLuint texUnit = 0;
    bool keepLooping=true;
    GLfloat rotate = 0.0f;
    try{
      while(keepLooping){

        // X11 junk
        for(int run=0; run < 3 && XPending(mDisplay) > 0; ++run){
          XNextEvent(mDisplay, &mEvent);
          switch (mEvent.type){
          case DestroyNotify:
            keepLooping = false;
            break;

          case ConfigureNotify:
            glViewport(0, 0, mEvent.xconfigure.width, mEvent.xconfigure.height);
            break;

          default:
            break;
          }
        }

        glEnable(GL_TEXTURE_2D);
        glDisable(GL_DITHER);
        glFrontFace(GL_CW);
        glClearColor(0.8f, 0.8f, 0.8f, 0.0f);
        glClearDepth(1.0f);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glShadeModel(GL_SMOOTH);

        glDepthFunc(GL_LEQUAL);
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(idShadeMain);

        for(short b=vertAtt_verts; b != vertAtt_MAX; ++b)
          glBindBuffer(GL_ARRAY_BUFFER, bufferIDs[b]);

        glUniform1i(idSample, texUnit); CHECKGL;
        glActiveTexture( static_cast<GLenum>(GL_TEXTURE0 + texUnit) ); CHECKGL;
        glBindTexture(GL_TEXTURE_2D, idTex); CHECKGL;

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffidIndexs); CHECKGL;
        glDrawElements(GL_TRIANGLES, sizeof(ibuff) / sizeof(ibuff[0]), GL_UNSIGNED_INT, 0); CHECKGL;

        if(mDoubleBuffered)
          glXSwapBuffers(mDisplay, mWindow);
        else
          glFlush();

        usleep(10);
      }
    }catch(...){
    }

    glDetachShader(idShadeMain, idVertShade);
    glDeleteShader(idVertShade);
    glDetachShader(idShadeMain, idFragShade);
    glDeleteShader(idFragShade);
    glDeleteProgram(idShadeMain);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDeleteBuffers(1, &buffidIndexs);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glDeleteBuffers(vertAtt_MAX, bufferIDs);

    glBindTexture(GL_TEXTURE_2D, 0);
    glDeleteTextures(1, &idTex);

    if(mContext){
      (void)glXMakeCurrent(mDisplay, None, NULL);
      glXDestroyContext(mDisplay, mContext);
      mContext = NULL;
    }

    XCloseDisplay(mDisplay);

  }catch(std::exception &e){
    std::cout << e.what() << std::endl;
  }

  return 0;
}

但遗憾的是我得到的是:

No texture

我的控制台输出是:

Version 1:
OpenGL=4.2.12337 Compatibility Profile Context 13.101
GLSL=4.30

我在片段着色器中尝试了以下测试:

static const char * codeFragmentShade = "\
#version 430\n\
  in vec4 col;\
  in vec2 texOut;\
  uniform sampler2D sampTex;\
  void main(){\
    gl_FragColor = texture(sampTex, texOut); gl_FragColor.r=textureSize( sampTex, 0 )[0]/2.0;\
  }\
";

Showing some texture info

static const char * codeFragmentShade = "\
#version 430\n\
  in vec4 col;\
  in vec2 texOut;\
  uniform sampler2D sampTex;\
  void main(){\
    gl_FragColor = texture(sampTex, texOut); gl_FragColor.rg=texOut;\
  }\
";

Showing texture coordinates

所以看起来我的贴图就在那里,但宽度是 1 像素左右。高度似乎为 0。

那我做错了什么?

最佳答案

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

你在这里请求 mipmap,但你的纹理不是 mipmap 完整的(这意味着你的纹理不能被采样):你只指定级别 0。你有几个选项:

  1. 禁用纹理映射,例如使用缩小过滤器 GL_LINEAR
  2. 手动指定整套 mimpap 级别。
  3. 通过调用 glGenerateMipmap() 使用自动 mipmap 生成在指定级别 0 的图像数据之后。

关于c++ - GLSL 4.3 纹理问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23847528/

相关文章:

c++ - 对 Variadic 模板与 Visual Studio 2010 的混淆

c++ - OpenGL 中的矩阵乘法顺序

c++ - Opengl统一行为

c++ - 通过 TCS 和 TES 传递数据

c++ - 将参数传递给构造函数和成员函数时 move 或复制

C++:如何读取 **argv 值并复制到字符串中

c++ - if(c.get_name(&name) && name && !strcmp(name, contName))

c++ - Opengl 64 位窗口

user-interface - OpenGL 应用程序的自动化测试

opengl - 如何实现广告牌?