首页 > 解决方案 > 如何为镶嵌矩形构建数据

问题描述

我无法弄清楚为镶嵌矩形构建数据所需的函数。

目前这是我为非镶嵌矩形所做的;

 GLuint Waveindices[] = {  
0, 1, 3, 
1, 2, 3  
};

std::vector<GLfloat> verticesRect;

  verticesRect = {
    // Positions        // Normal Coords          // Texture Coords
    width,  height, 0.0f,    0.0 , 0.0, 1.0 ,     1.0f, 0.0f,   // Top Right
    width, -height, 0.0f,    0.0 , 0.0, 1.0 ,     1.0f, 1.0f,   // Bottom Right
   -width, -height, 0.0f,    0.0 , 0.0, 1.0 ,     0.0f, 1.0f,   // Bottom Left
   -width, height, 0.0f,    0.0 , 0.0, 1.0 ,     0.0f, 0.0f    // Top Left 

 glGenVertexArrays(1, &m_VAO);
 glGenBuffers(1, &m_VBO);
 glGenBuffers(1, &m_EBO);
 glBindVertexArray(m_VAO);
 glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
 glBufferData(GL_ARRAY_BUFFER, verticesRect.size() * sizeof(GLfloat), &verticesRect[0], 
 GL_STATIC_DRAW);
 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Waveindices), Waveindices, GL_STATIC_DRAW);
 glEnableVertexAttribArray(0);
 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
 glEnableVertexAttribArray(1);
 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
 glEnableVertexAttribArray(0);
 glEnableVertexAttribArray(2);
 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
};

抱歉,对于我尝试过的选项,我没有任何代码,因为我无法从我编写的代码中获得任何有意义的完整输出。

这是 Tessellation 值为 2 时矩形的外观。

在此处输入图像描述

标签: opengl

解决方案


您需要的是在边缘点之间进行线性插值...计算 x、y、z,设置纹理坐标并在完成后使用叉积重新计算法线。然后只需创建三角剖分并渲染...

这里是简单的 C++(旧 api)示例:

GLfloat divide(GLfloat a,GLfloat b){ if (fabs(b)<1e-10) return 0.0; else return a/b; }
void  normalize(GLfloat *c,GLfloat *a)  // c = a/|a|
    {
    GLfloat l=divide(1.0,sqrt((a[0]*a[0])+(a[1]*a[1])+(a[2]*a[2])));
    c[0]=a[0]*l;
    c[1]=a[1]*l;
    c[2]=a[2]*l;
    }
void  cross(GLfloat *c,GLfloat *a,GLfloat *b) // c = cross(a,b)
    {
    GLfloat   q[3];
    q[0]=(a[1]*b[2])-(a[2]*b[1]);
    q[1]=(a[2]*b[0])-(a[0]*b[2]);
    q[2]=(a[0]*b[1])-(a[1]*b[0]);
    for(int i=0;i<3;i++) c[i]=q[i];
    }
void genere(GLfloat w,GLfloat h)
    {
    const int m=16,n=16;        // points per grid axis
    const int n8=n*8;           // size of VBO gfx data
    const int sz0=m*n8;         // size of VBO gfx data
    const int sz1=(m-1)*(n-1)*6;// size of indices
    GLfloat dat[sz0];
    GLuint idx[sz1];
    int i,j,k,a,b;
    GLfloat x,y,z,dx,dy,l;
    GLfloat u[3],v[3],nor[3];
    // gfx data
    dx=2.0*w/GLfloat(n-1);
    dy=2.0*h/GLfloat(m-1);
    for (a=0,y=-h,j=0;j<m;j++,y+=dy)
     for (    x=-w,i=0;i<n;i++,x+=dx)
        {
        // Vertex
        z=0.3*sin((x*x)+(y*y));
        dat[a]=x; a++;
        dat[a]=y; a++;
        dat[a]=z; a++;
        // Normal (will be recomputed latter)
        dat[a]=0.0; a++;
        dat[a]=0.0; a++;
        dat[a]=1.0; a++;
        // TexCoord
        dat[a]=(x+w)/(w+w); a++;
        dat[a]=(y+h)/(h+h); a++;
        }
    // triangulation indices
    for (a=0,j=1;j<m;j++)
     for (    i=1;i<n;i++)
        {
        // b = location of point[i,j] in dat[]
        b=((n*j)+i)*8;
        // first triangle per quad
        idx[a]=b-8;    a++;
        idx[a]=b-8-n8; a++;
        idx[a]=b;      a++;
        // second triangle per quad
        idx[a]=b-8-n8; a++;
        idx[a]=b-n8;   a++;
        idx[a]=b;      a++;
        // recompute inner normals
        for (k=0;k<3;k++)
            {
            u[k]=dat[idx[a-6]+k]-dat[idx[a-4]+k];
            v[k]=dat[idx[a-5]+k]-dat[idx[a-4]+k];
            }
        cross(nor,u,v); normalize(nor,nor);
        for (k=0;k<3;k++)
            {
            u[k]=dat[idx[a-3]+k]-dat[idx[a-1]+k];
            v[k]=dat[idx[a-2]+k]-dat[idx[a-1]+k];
            }
        cross(u,u,v); normalize(u,u);
        for (k=0;k<3;k++) dat[idx[a-1]+3+k]=0.5*(nor[k]+u[k]);
        }
    // copy edge normals
    for (j=0,i=1;i<n;i++)
        {
        // b = location of point[i,j] in dat[]
        b=((n*j)+i)*8;
        // copy
        for (k=0;k<3;k++) dat[b+3+k]=dat[b+3+k+n8];
        }
    for (i=0,j=1;j<m;j++)
        {
        // b = location of point[i,j] in dat[]
        b=((n*j)+i)*8;
        // copy
        for (k=0;k<3;k++) dat[b+3+k]=dat[b+3+k+8];
        }

    // old api render (just for debug ignore this)
    glBegin(GL_TRIANGLES);
    for (i=0;i<sz1;i++)
        {
        j=idx[i];
        glNormal3fv(dat+j+3);
        glTexCoord3fv(dat+j+6);
        glVertex3fv(dat+j);
        }
    glEnd();
    }

请注意,法线是单面的,因此您的照明方程应该处理否则一侧会因照明而变暗。

法线在每个网格单元中的 2 个三角形之间平均(如果您想要更平滑的表面,平均 4 个三角形)。

这里预览:

预览

如果我没有在某个地方犯任何愚蠢的错误,那么数据格式应该与您的匹配......所以只需删除旧的 api 渲染并添加 VBO 内容而不是它


推荐阅读