凹凸贴图:这个教科书的例子有什么问题?

时间:2021-09-17 23:45:50

Here's what the README says this example does: "bump map on one polygon with a rotation light". Let me add: the polygon is a square, and the bump map on it should produce a raised-looking square within the original polygon square. The values for i and j (pixel iteration) in the second 'for' loop in main() are indicative of this inner square pattern.

这里是README说的这个例子:“一个带有旋转光的多边形的凹凸贴图”。让我补充一下:多边形是一个正方形,它的凹凸贴图应该在原来的多边形正方形内产生一个凸出的正方形。main()中第二个for循环中的i和j(像素迭代)的值指示了这个内方模式。

Problem: When I run it, the display window comes up but it's blank white. Maybe you can try running it yourself: if it works, let's find differences in our setup; if it, doesn't please help find what's wrong with the code. The code is here: http://www.cs.unm.edu/~angel/BOOK/INTERACTIVE_COMPUTER_GRAPHICS/SIXTH_EDITION/. Click on "Code", then "CHAPTER07/". It's example 7.3. Also, below is the code for reference. Note: I added "#version 150" to fshader73.glsl to get rid of a version error at runtime.

问题:当我运行它时,显示窗口出现了,但它是空白的白色。也许你可以试着自己运行它:如果它有效,让我们在我们的设置中找出差异;如果是,请帮忙找出代码有什么问题。这里的代码是:http://www.cs.unm.edu// ~angel/BOOK/INTERACTIVE_COMPUTER_GRAPHICS/SIXTH_EDITION/。点击“代码”,然后是“CHAPTER07/”。7.3的例子。下面是参考代码。注意:我给fshader73添加了“#version 150”。glsl在运行时清除版本错误。

example3.cpp:

example3.cpp:

/* sets up flat mesh */
/* sets up elapsed time parameter for use by shaders */

#include "Angel.h"

#define N 256

GLfloat normals[N][N][3];
GLuint         program;
GLuint        texMapLocation;
GLfloat tangent[3] = {1.0, 0.0, 0.0};

typedef Angel::vec4  point4;
typedef Angel::vec4  color4;

point4 points[6];
vec2 tex_coord[6];
mat4 ctm, projection;

vec4 normal = point4(0.0, 1.0, 0.0, 0.0);
color4 light_diffuse = color4(1.0, 1.0, 1.0, 1.0);
color4 material_diffuse = color4(0.7, 0.7, 0.7, 1.0);
point4  light_position = point4(0.0, 10.0, 0.0, 1.0);
vec4 eye =  vec4(2.0, 2.0, 2.0, 1.0);
vec4 at = vec4(0.5, 0.0, 0.5, 1.0);
vec4 up = vec4(0.0, 1.0, 0.0, 1.0);



GLuint loc, loc2;
GLuint buffers[2];

GLuint normal_loc;
GLuint diffuse_product_loc;
GLuint light_position_loc;
GLuint ctm_loc, projection_loc;
GLuint tangent_loc;


/* standard OpenGL initialization */

vec4 product(vec4 a, vec4 b)
{
  return vec4(a[0]*b[0], a[1]*b[1], a[2]*b[2], a[3]*b[3]);
}
static void init()
{
    const float meshColor[]     = {0.7f, 0.7f, 0.7f, 1.0f}; 

    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, meshColor);

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    glBindTexture(GL_TEXTURE_2D, 0);
    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_RGBA, N, N, 0, GL_RGB, GL_FLOAT, normals);
    glEnable(GL_TEXTURE_2D);


    glEnable(GL_DEPTH_TEST);

   loc = glGetAttribLocation(program, "vPosition");
   glEnableVertexAttribArray(loc);
   glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, points);

   loc2 = glGetAttribLocation(program, "texcoord");
   glEnableVertexAttribArray(loc2);
   glVertexAttribPointer(loc2, 2, GL_FLOAT, GL_FALSE, 0, tex_coord);

   glGenBuffers(2, buffers);
   glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
   glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

   tangent_loc = glGetUniformLocation(program, "objTangent");
   glUniform3fv(tangent_loc, 3, tangent);

   normal_loc = glGetUniformLocation(program, "Normal");
   glUniform4fv(normal_loc, 4, normal);

   vec4 diffuse_product = product(light_diffuse, material_diffuse);
   diffuse_product_loc = glGetUniformLocation(program, "DiffuseProduct");
   glUniform4fv(diffuse_product_loc, 4, diffuse_product);

   light_position_loc = glGetUniformLocation(program, "LightPosition");
   glUniform4fv(light_position_loc, 4, light_position);

   ctm_loc = glGetUniformLocation(program, "ModelView");
   ctm = LookAt(eye, at , up);
   glUniformMatrix4fv(ctm_loc, 16, GL_TRUE, ctm);

   mat4 nm;
   GLfloat det;
   det = ctm[0][0]*ctm[1][1]*ctm[2][2]+ctm[0][1]*ctm[1][2]*ctm[2][1]
     -ctm[2][0]*ctm[1][1]*ctm[0][2]-ctm[1][0]*ctm[0][1]*ctm[2][2]-ctm[0][0]*ctm[1][2]*ctm[2][1];
   nm[0][0] = (ctm[1][1]*ctm[2][2]-ctm[1][2]*ctm[2][1])/det;
   nm[0][1] = -(ctm[0][1]*ctm[2][2]-ctm[0][2]*ctm[2][1])/det;
   nm[0][2] = (ctm[0][1]*ctm[2][0]-ctm[2][1]*ctm[2][2])/det;
   nm[1][0] = -(ctm[0][1]*ctm[2][2]-ctm[0][2]*ctm[2][1])/det;
   nm[1][1] = (ctm[0][0]*ctm[2][2]-ctm[0][2]*ctm[2][0])/det;
   nm[1][2] = -(ctm[0][0]*ctm[2][1]-ctm[2][0]*ctm[0][1])/det;
   nm[2][0] = (ctm[0][1]*ctm[1][2]-ctm[1][1]*ctm[0][2])/det;
   nm[2][1] = -(ctm[0][0]*ctm[1][2]-ctm[0][2]*ctm[1][0])/det;
   nm[2][2] = (ctm[0][0]*ctm[1][1]-ctm[1][0]*ctm[0][1])/det;

    GLuint nm_loc;
    nm_loc = glGetUniformLocation(program, "NormalMatrix");
    glUniformMatrix4fv(nm_loc, 16, GL_TRUE, nm);

    projection_loc = glGetUniformLocation(program, "Projection");
    projection = Ortho(-0.75,0.75,-0.75,0.75,-5.5,5.5);
    glUniformMatrix4fv(projection_loc, 16, GL_TRUE, projection);

    texMapLocation = glGetUniformLocation(program, "texMap");

}

    /* set up uniform parameter */

void mesh()
{
      point4 vertices[4] = {point4(0.0, 0.0, 0.0, 1.0), point4(1.0, 0.0, 0.0, 1.0),
         point4(1.0, 0.0, 1.0, 1.0), point4(0.0, 0.0, 1.0, 1.0)};

       points[0] = vertices[0];
       tex_coord[0] = vec2(0.0, 0.0);
       points[1] = vertices[1];
       tex_coord[1] = vec2(1.0, 0.0);
       points[2] = vertices[2];
       tex_coord[2] = vec2(1.0, 1.0);
       points[3] = vertices[2];
       tex_coord[3] = vec2(1.0, 1.0);
       points[4] = vertices[3];
       tex_coord[4] = vec2(0.0, 1.0);
       points[5] = vertices[0];
       tex_coord[5] = vec2(0.0, 0.0);
}

static void draw()
{

    glUniform1i(texMapLocation, 0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    mesh(); 

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glutSwapBuffers();
}

static void reshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glutPostRedisplay();
}

static void keyboard(unsigned char key, int x, int y)
{
    switch (key) {
    case 27:
    case 'Q':
    case 'q':
        exit(EXIT_SUCCESS);
    }
}

void idle()
{
   int t;
   t = glutGet(GLUT_ELAPSED_TIME);
   light_position[0] = 5.5*sin(0.001*t);
   light_position[2] = 5.5*cos(0.001*t);
   glUniform4fv(light_position_loc, 4, light_position);
   glutPostRedisplay();
}

int main(int argc, char** argv)
{
    int i,j, k;
    float d;

    float data[N+1][N+1];
    for(i=0;i<N+1;i++) for(j=0;j<N+1;j++) data[i][j]=0.0;
    for(i=N/4; i< 3*N/4; i++) for(j=N/4;j<3*N/4;j++) data[i][j] = 1.0;

    for(i=0;i<N;i++) for(j=0;j<N;j++)
    {
       normals[i][j][0] = data[i][j]-data[i+1][j];
       normals[i][j][2] = data[i][j]-data[i][j+1];
       normals[i][j][1]= 1.0;
    }


    for(i=0;i<N;i++) for(j=0;j<N;j++)
    {
       d = 0.0;
       for(k=0;k<3;k++) d+=normals[i][j][k]*normals[i][j][k];
       d=sqrt(d);
       for(k=0;k<3;k++) normals[i][j][k]= 0.5*normals[i][j][k]/d+0.5;
    }

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(1024, 1024);

    glutInitContextVersion( 3, 2 );
    glutInitContextProfile( GLUT_CORE_PROFILE );

    glutCreateWindow("Simple GLSL example");
    glutDisplayFunc(draw);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutIdleFunc(idle);

    glewInit();

    program = InitShader("vshader73.glsl", "fshader73.glsl");
    init();


    glutMainLoop();
    return 0;
}

vshader73.glsl:

vshader73.glsl:

/* bump map vertex shader */

#version 150

out vec3 L; /* light vector in texture-space coordinates */
out vec3 V; /* view vector in texture-space coordinates */

in vec2 texcoord;
in vec4 vPosition;

uniform vec4 Normal;
uniform vec4 LightPosition;
uniform mat4 ModelView;
uniform mat4 Projection;
uniform mat4 NormalMatrix;
uniform vec3 objTangent; /* tangent vector in object coordinates */

out vec2 st;

void main()
{
    mat3 NM3;

    NM3[0][0] = NormalMatrix[0][0];
    NM3[0][1] = NormalMatrix[0][1];
    NM3[0][2] = NormalMatrix[0][2];
    NM3[1][0] = NormalMatrix[1][0];
    NM3[1][1] = NormalMatrix[1][1];
    NM3[1][2] = NormalMatrix[1][2];
    NM3[2][0] = NormalMatrix[2][0];
    NM3[2][1] = NormalMatrix[2][1];
    NM3[2][2] = NormalMatrix[2][2];

    gl_Position = Projection*ModelView*vPosition;


    st = texcoord;

    vec3 eyePosition = vec3(ModelView*vPosition);
    vec3 eyeLightPos = LightPosition.xyz;

   /* normal, tangent and binormal in eye coordinates */

    vec3 N = normalize(NM3*Normal.xyz);
    vec3 T  = normalize(NM3*objTangent);
    vec3 B = cross(N, T);

    /* light vector in texture space */

    L.x = dot(T, eyeLightPos-eyePosition);
    L.y = dot(B, eyeLightPos-eyePosition);
    L.z = dot(N, eyeLightPos-eyePosition);

    L = normalize(L);

    /* view vector in texture space */

    V.x = dot(T, -eyePosition);
    V.y = dot(B, -eyePosition);
    V.z = dot(N, -eyePosition);

    V = normalize(V);
}

fshader73.glsl:

fshader73.glsl:

#version 150

in vec3 L;
in vec3 V;
uniform sampler2D texMap;
in vec2 st;
uniform vec4 DiffuseProduct;

out vec4 fColor;

void main()
{

   vec4 N = texture2D(texMap, st);
   vec3 NN =  normalize(2.0*N.xyz-1.0);
   vec3 LL = normalize(L);
   float Kd = max(dot(NN.xyz, LL), 0.0);
   fColor = Kd*DiffuseProduct;
}

EDIT:

编辑:

Following Brett's comment, I replaced glBindTexture(GL_TEXTURE_2D, 0) with the below -- still getting a blank white window:

在Brett的评论之后,我替换了glbind纹理(GL_TEXTURE_2D, 0),下面是一个空白的白色窗口:

GLuint texture;
glGenTextures( 1, &texture );
glBindTexture(GL_TEXTURE_2D, texture);
...
glActiveTexture(GL_TEXTURE0);

2 个解决方案

#1


1  

My comment went just over the limit of characters, so hopefully this is worth an answer.

我的评论刚刚超过了字符的极限,所以希望这是值得的。

The only thing I can see that might be a problem are your glUniformMatrix4fv calls. The second parameter, according to the OpenGl 4 language reference describes it as the number of matrices to change. The 3.2 core reference pages aren't linked on their site, so I couldn't look it up for that particular context. So for glUniformMatrix4fv(projection_loc, 16, GL_TRUE, projection); it intends to find sixteen matrices in an array called "Projection", yet you only defined uniform mat4 Projection;. This may or may not be a part of your problem, and it's possible I'm not even correct, especially if this is a known tutorial that other people have compiled/used.

我唯一能看到的可能是你的glUniformMatrix4fv调用。第二个参数,根据OpenGl 4语言引用将其描述为要改变的矩阵的数量。3.2核心参考页面并没有链接到他们的网站上,所以我无法查找到那个特定的上下文。所以对于glUniformMatrix4fv(projection_loc, 16, GL_TRUE,投影);它打算在一个名为“投影”的数组中找到16个矩阵,但你只定义了均匀的mat4投影;这可能是问题的一部分,也可能不是问题的一部分,我甚至都不正确,特别是如果这是其他人已经编译/使用过的教程。

Also, glEnable(GL_TEXTURE_2D) isn't necessary (or even usable, i think?) with an OpenGL context of version 3.2 core, which was set up here:

另外,glEnable(GL_TEXTURE_2D)并不是必需的(我认为甚至是可用的),它有一个版本3.2核心的OpenGL上下文,它是在这里设置的:

glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );

If the compiler isn't giving you any errors, trying adding glGetError() after lines which you think may be problematic. The return value maps to an enum value in the header file for OpenGL (glcorearb.h will list them), and i think the documentation lists them as well.

如果编译器没有给您任何错误,那么尝试在您认为可能存在问题的行之后添加glge恐怖()。返回值映射到OpenGL的头文件中的枚举值(glcorearb)。h将列出它们),我认为文档也列出了它们。

Other than that, you may just want to check that the "normals" 3-dimensional array is laid out in memory the way you expect it to be, as I've never tried manually constructing an array to be used as a texture myself (though images are basically strings of byte data anyways, so I don't see how it's a problem in this case).

除此之外,你可能只是想检查“法线”三维数组在内存的方式是你希望的,我从来没有尝试手动构建数组用作纹理自己(虽然图片基本上都是字符串的字节数据无论如何,所以我不知道这是一个问题,在这种情况下)。

Hopefully this helped you, or at least pointed you in the right direction. Good luck.

希望这对你有帮助,或者至少指出了正确的方向。祝你好运。

Edit #1: I realized my comment about shader checking wasn't very complete, as I failed to mention some API calls. Here's an example of it though:

编辑#1:我意识到我对shader检查的评论不是很完整,因为我没有提到一些API调用。这里有一个例子:

      char * dataBuffer;
      struct _stat fileStat;
      long fLen;
      FILE * vSh;
      FILE * fSh;
      int desc;

      GLint status;
      GLint logLength;

      GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
      //errort = glGetError();
      GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
      GLuint program = glCreateProgram();
      /*__________________________________________________*/

      vSh = fopen("vShader.vSh", "r");
      desc = _fileno(vSh);
      _fstat(desc, &fileStat);

      fLen = fileStat.st_size;

      dataBuffer = (char *) calloc((fLen + 1), sizeof(char));
      if (dataBuffer == NULL)
      {
            MessageBox(NULL, "Malloc failure: VS", "Create Program", MB_OK | MB_ICONINFORMATION);
            return 1;
      }


      if(feof(vSh) == 0)
      {
            MessageBox(NULL, "Did not reach EoF for VS", "Create Program", MB_OK | MB_ICONINFORMATION);
            return 2;
      }
      fclose(vSh);

      glShaderSource(vShader, 1, &dataBuffer, NULL);
      glCompileShader(vShader);

      //Error checking
      glGetShaderiv(vShader, GL_COMPILE_STATUS, &status);
      if (status == GL_FALSE)
      {
            glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLength);
            char resultV[logLength+1];
            glGetShaderInfoLog(vShader, logLength, NULL, resultV);

            MessageBox(NULL, resultV, "Vertex Compile Error", MB_OK);
      }
      free(dataBuffer);

The way I get my shader isn't the real important part, so hopefully that doesn't confuse you. The part labelled //Error checking is the stuff I meant, when talking about checking your shader for errors.

我得到着色的方法不是很重要的部分,所以希望这不会让你们迷惑。在讨论检查您的着色器错误时,标记//错误检查的部分是我的意思。

#2


0  

Alex my friend you were close! Basically, EVERY glUniform... call in there, not just the glUniformMatrix... ones, need 1 as their second argument.

亚历克斯,我的朋友,你离我很近!基本上,每glUniform……在这里调用,而不仅仅是glUniformMatrix…1作为第二个参数。

#1


1  

My comment went just over the limit of characters, so hopefully this is worth an answer.

我的评论刚刚超过了字符的极限,所以希望这是值得的。

The only thing I can see that might be a problem are your glUniformMatrix4fv calls. The second parameter, according to the OpenGl 4 language reference describes it as the number of matrices to change. The 3.2 core reference pages aren't linked on their site, so I couldn't look it up for that particular context. So for glUniformMatrix4fv(projection_loc, 16, GL_TRUE, projection); it intends to find sixteen matrices in an array called "Projection", yet you only defined uniform mat4 Projection;. This may or may not be a part of your problem, and it's possible I'm not even correct, especially if this is a known tutorial that other people have compiled/used.

我唯一能看到的可能是你的glUniformMatrix4fv调用。第二个参数,根据OpenGl 4语言引用将其描述为要改变的矩阵的数量。3.2核心参考页面并没有链接到他们的网站上,所以我无法查找到那个特定的上下文。所以对于glUniformMatrix4fv(projection_loc, 16, GL_TRUE,投影);它打算在一个名为“投影”的数组中找到16个矩阵,但你只定义了均匀的mat4投影;这可能是问题的一部分,也可能不是问题的一部分,我甚至都不正确,特别是如果这是其他人已经编译/使用过的教程。

Also, glEnable(GL_TEXTURE_2D) isn't necessary (or even usable, i think?) with an OpenGL context of version 3.2 core, which was set up here:

另外,glEnable(GL_TEXTURE_2D)并不是必需的(我认为甚至是可用的),它有一个版本3.2核心的OpenGL上下文,它是在这里设置的:

glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );

If the compiler isn't giving you any errors, trying adding glGetError() after lines which you think may be problematic. The return value maps to an enum value in the header file for OpenGL (glcorearb.h will list them), and i think the documentation lists them as well.

如果编译器没有给您任何错误,那么尝试在您认为可能存在问题的行之后添加glge恐怖()。返回值映射到OpenGL的头文件中的枚举值(glcorearb)。h将列出它们),我认为文档也列出了它们。

Other than that, you may just want to check that the "normals" 3-dimensional array is laid out in memory the way you expect it to be, as I've never tried manually constructing an array to be used as a texture myself (though images are basically strings of byte data anyways, so I don't see how it's a problem in this case).

除此之外,你可能只是想检查“法线”三维数组在内存的方式是你希望的,我从来没有尝试手动构建数组用作纹理自己(虽然图片基本上都是字符串的字节数据无论如何,所以我不知道这是一个问题,在这种情况下)。

Hopefully this helped you, or at least pointed you in the right direction. Good luck.

希望这对你有帮助,或者至少指出了正确的方向。祝你好运。

Edit #1: I realized my comment about shader checking wasn't very complete, as I failed to mention some API calls. Here's an example of it though:

编辑#1:我意识到我对shader检查的评论不是很完整,因为我没有提到一些API调用。这里有一个例子:

      char * dataBuffer;
      struct _stat fileStat;
      long fLen;
      FILE * vSh;
      FILE * fSh;
      int desc;

      GLint status;
      GLint logLength;

      GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
      //errort = glGetError();
      GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
      GLuint program = glCreateProgram();
      /*__________________________________________________*/

      vSh = fopen("vShader.vSh", "r");
      desc = _fileno(vSh);
      _fstat(desc, &fileStat);

      fLen = fileStat.st_size;

      dataBuffer = (char *) calloc((fLen + 1), sizeof(char));
      if (dataBuffer == NULL)
      {
            MessageBox(NULL, "Malloc failure: VS", "Create Program", MB_OK | MB_ICONINFORMATION);
            return 1;
      }


      if(feof(vSh) == 0)
      {
            MessageBox(NULL, "Did not reach EoF for VS", "Create Program", MB_OK | MB_ICONINFORMATION);
            return 2;
      }
      fclose(vSh);

      glShaderSource(vShader, 1, &dataBuffer, NULL);
      glCompileShader(vShader);

      //Error checking
      glGetShaderiv(vShader, GL_COMPILE_STATUS, &status);
      if (status == GL_FALSE)
      {
            glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLength);
            char resultV[logLength+1];
            glGetShaderInfoLog(vShader, logLength, NULL, resultV);

            MessageBox(NULL, resultV, "Vertex Compile Error", MB_OK);
      }
      free(dataBuffer);

The way I get my shader isn't the real important part, so hopefully that doesn't confuse you. The part labelled //Error checking is the stuff I meant, when talking about checking your shader for errors.

我得到着色的方法不是很重要的部分,所以希望这不会让你们迷惑。在讨论检查您的着色器错误时,标记//错误检查的部分是我的意思。

#2


0  

Alex my friend you were close! Basically, EVERY glUniform... call in there, not just the glUniformMatrix... ones, need 1 as their second argument.

亚历克斯,我的朋友,你离我很近!基本上,每glUniform……在这里调用,而不仅仅是glUniformMatrix…1作为第二个参数。