opengl 微小的渲染故障,需要帮助和提示

Posted

技术标签:

【中文标题】opengl 微小的渲染故障,需要帮助和提示【英文标题】:opengl tiny rendering glitch, need help & tips 【发布时间】:2013-05-17 15:46:51 【问题描述】:

这是我的代码:

#include <stdlib.h>
#include <iostream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <SDL.h>

using namespace std;

typedef unsigned short us;
typedef unsigned char uc;

bool *keystates = new bool[256];
bool *skeystates= new bool[256];
uc dir_m[8][2]=
     0, 1 ,
     0,-1 ,
     -1,0 ,
     1,0 ,
     1,1,
     1,-1 ,
     -1,-1 ,
     -1,1 
;

us totalbots=15;

float zoomlvl=-70.f;
float camx=0.f,camy=0.f;

struct bot_data
    float x,y,z;
    float r,g,b;
    float size; //    "radius" of the square
    us coold;
    us age;
    us trans:5;
    us dir:3,fac:2;
    bot_data(void);
    void move(void);
    void deliver(us bot);
;
struct bool_data
    bool ch:1,ch2:1;
;

bot_data::bot_data(void)
    size=0.25f;
    fac=rand()%4;
    switch(fac)
    case 0:x=10.f,y=10.f,z=0.f;
        r=1.0f,g=0.f,b=0.f;
        break;
    case 1:x=-10.f,y=-10.f,z=0.f;
        r=0.0f,g=0.f,b=1.f;
        break;
    case 2:x=-10.f,y=10.f,z=0.f;
        r=1.0f,g=1.f,b=0.f;
        break;
    case 3:x=10.f,y=-10.f,z=0.f;
        r=0.0f,g=1.f,b=0.f;
        break;
    
    coold=0;
    trans=0;
    age=0;
    dir=rand()%8;


bot_data *cubers=new bot_data[65536];
bool_data *bools=new bool_data;

void bot_data::move(void)
    float move=size/10.f;
    switch(dir)
    case 0:y+=move;
        break;
    case 1:y-=move;
        break;
    case 2:x-=move;
        break;
    case 3:x+=move;
        break;
    case 4:x+=move;
        y+=move;
        break;
    case 5:x+=move;
        y-=move;
        break;
    case 6:y-=move;
        x-=move;
        break;
    case 7:y+=move;
        x-=move;
        break;
    

void bot_data::deliver(us bot)
    age=-10;
    totalbots+=3;
    float tmp=size-(size/4.f);
    size=0.25f;
    x-=size;
    y+=size;
    for(uc i=1;i<=3;i++)
        cubers[totalbots-i].fac=fac;
        switch(fac)
        case 0:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=0.f;
            break;
        case 1:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=1.f;
            break;
        case 2:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
            break;
        case 3:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
            break;
        
        cubers[totalbots-i].coold=coold;
        cubers[totalbots-i].size=size;
        switch(i)
        case 1:cubers[totalbots-i].x=x;
            cubers[totalbots-i].y=y-size*2;
            break;
        case 2:cubers[totalbots-i].x=x+size*2;
            cubers[totalbots-i].y=y;
            break;
        case 3:cubers[totalbots-i].x=x+size*2;
            cubers[totalbots-i].y=y-size*2;
            break;
        
    


void initkeys(void)
    for(uc i=0;i<255;i++)
        keystates[i]=false;
        skeystates[i]=false;
    

void p_keys(unsigned char key, int x, int y)
    keystates[key]=true;

void keyup(unsigned char key, int x, int y)
    keystates[key]=false;

void sp_keys(int key, int x, int y)
    skeystates[key]=true;

void skeyup(int key, int x, int y)
    skeystates[key]=false;

void key_func(void)
    if (keystates['z'])
        if(skeystates[GLUT_KEY_UP])zoomlvl+=1.f;
        else if (skeystates[GLUT_KEY_DOWN])zoomlvl-=1.f;
        if(zoomlvl<-100.0f)zoomlvl=-100.f;
        else if(zoomlvl>-5.f)zoomlvl=-5.f;
    
    else
        if(skeystates[GLUT_KEY_UP])camy-=1.f;
        else if(skeystates[GLUT_KEY_DOWN])camy+=1.f;
    
    if(skeystates[GLUT_KEY_LEFT])camx+=1.f;
    else if(skeystates[GLUT_KEY_RIGHT])camx-=1.f;

void render_p(us bot)
    glColor3f(cubers[bot].r,cubers[bot].g,cubers[bot].b);
    glBegin(GL_QUADS);
    glVertex2f(cubers[bot].size,cubers[bot].size);
    glVertex2f(cubers[bot].size,-cubers[bot].size);
    glVertex2f(-cubers[bot].size,-cubers[bot].size);
    glVertex2f(-cubers[bot].size,cubers[bot].size);
    glEnd();

void process_cubers(void)
    for(us i=0;i<totalbots;i++)
        //glPushMatrix();
        glLoadIdentity();
        glTranslatef(cubers[i].x,cubers[i].y,cubers[i].z);
        if(cubers[i].coold==0)
            cubers[i].move();
            cubers[i].trans++;
            if(cubers[i].trans==20)
                cubers[i].trans=0;
                cubers[i].coold=50;
                if(cubers[i].age<100)
                    cubers[i].size+=0.025f;
                
                else if(cubers[i].age==150)
                    cubers[i].deliver(i);
                
                cubers[i].dir=rand()%8;
                cubers[i].age+=10;
            
        
        else cubers[i].coold--;
        render_p(i);
        //glPopMatrix();
    

void display(void)
    key_func();
    glClearColor(0.6f,0.6f,0.6f,1.f);
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(camx,camy,zoomlvl);
    process_cubers();
    glutSwapBuffers();
    SDL_Delay(1000/30);
    glutPostRedisplay();

void resize(int width,int height)
    glViewport(0,0,(GLsizei)width,(GLsizei)height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60,(GLfloat)width/(GLfloat)height,1.f,100.f);
    glMatrixMode(GL_MODELVIEW);

int main (int argc, char **argv) 
    initkeys();
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE);
    glutInitWindowSize (640, 480);
    glutInitWindowPosition (0, 0); 
    glutCreateWindow ("opengl 1");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutReshapeFunc(resize);
    glutKeyboardFunc(p_keys);
    glutKeyboardUpFunc(keyup);
    glutSpecialFunc(sp_keys);
    glutSpecialUpFunc(skeyup);
    glutMainLoop();
    return 0;

它呈现一定数量的所述方块,这些方块在每个特定间隔移动。他们的移动距离就是他们的大小。每次他们移动时,它们的大小都会增长,直到达到大小限制(在这种情况下为半径为 1.f)经过一定数量的移动(在这种情况下为 15),方格将分成 4 个较小的方格并填满确切的空间它的前身被占用,这意味着它应该看起来完全无缝。问题是相反,我在方形分割后得到了这种瞬间撕裂和故障外观的渲染,但除此之外我没有发现其他问题。

我怀疑也许我错过了一些我应该在渲染新的 3 个方块时调用的 gl 函数(分裂是通过添加 3 个新方块并将当前的一个缩小到其大小的四分之一,然后调整所有方格。)

【问题讨论】:

GLUT xor SDL:选择一个并且只有一个框架。如果您想在 GLUT 中限制帧,请使用 glutTimerFunc() 重新启动计时器并启动 glutPostRedisplay() 好主意,我在制作这个时实现帧速率真的很便宜,所以我选择了 sdl。我会改的 【参考方案1】:

试试这个:

#include <GL/glew.h>
#include <GL/glut.h>

typedef unsigned short us;
typedef unsigned char uc;

bool *keystates = new bool[256];
bool *skeystates= new bool[256];
uc dir_m[8][2]=

     0, 1 ,
     0,-1 ,
     -1,0 ,
     1,0 ,
     1,1,
     1,-1 ,
     -1,-1 ,
     -1,1 
;

us totalbots=15;

float zoomlvl=-70.f;
float camx=0.f,camy=0.f;

struct bot_data

    float x,y,z;
    float r,g,b;
    float size; //    "radius" of the square
    us coold;
    us age;
    us trans:5;
    us dir:3,fac:2;
    bot_data(void);
    void move(void);
    void deliver(us bot);
;

struct bool_data

    bool ch:1,ch2:1;
;

bot_data::bot_data(void)

    size=0.25f;
    fac=rand()%4;
    switch(fac)
    case 0:x=10.f,y=10.f,z=0.f;
        r=1.0f,g=0.f,b=0.f;
        break;
    case 1:x=-10.f,y=-10.f,z=0.f;
        r=0.0f,g=0.f,b=1.f;
        break;
    case 2:x=-10.f,y=10.f,z=0.f;
        r=1.0f,g=1.f,b=0.f;
        break;
    case 3:x=10.f,y=-10.f,z=0.f;
        r=0.0f,g=1.f,b=0.f;
        break;
    
    coold=0;
    trans=0;
    age=0;
    dir=rand()%8;


bot_data *cubers=new bot_data[65536];
bool_data *bools=new bool_data;

void bot_data::move(void)

    float move=size/10.f;
    switch(dir)
    case 0:y+=move;
        break;
    case 1:y-=move;
        break;
    case 2:x-=move;
        break;
    case 3:x+=move;
        break;
    case 4:x+=move;
        y+=move;
        break;
    case 5:x+=move;
        y-=move;
        break;
    case 6:y-=move;
        x-=move;
        break;
    case 7:y+=move;
        x-=move;
        break;
    


void bot_data::deliver(us bot)

    age=-10;
    totalbots+=3;
    float tmp=size-(size/4.f);
    size=0.25f;
    x-=size;
    y+=size;
    for(uc i=1;i<=3;i++)
        cubers[totalbots-i].fac=fac;
        switch(fac)
        case 0:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=0.f;
            break;
        case 1:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=0.f,cubers[totalbots-i].b=1.f;
            break;
        case 2:cubers[totalbots-i].r=1.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
            break;
        case 3:cubers[totalbots-i].r=0.0f,cubers[totalbots-i].g=1.f,cubers[totalbots-i].b=0.f;
            break;
        
        cubers[totalbots-i].coold=coold;
        cubers[totalbots-i].size=size;
        switch(i)
        case 1:cubers[totalbots-i].x=x;
            cubers[totalbots-i].y=y-size*2;
            break;
        case 2:cubers[totalbots-i].x=x+size*2;
            cubers[totalbots-i].y=y;
            break;
        case 3:cubers[totalbots-i].x=x+size*2;
            cubers[totalbots-i].y=y-size*2;
            break;
        
    


void initkeys(void)

    for(uc i=0;i<255;i++)
        keystates[i]=false;
        skeystates[i]=false;
    


void p_keys(unsigned char key, int x, int y)

    keystates[key]=true;


void keyup(unsigned char key, int x, int y)

    keystates[key]=false;


void sp_keys(int key, int x, int y)

    skeystates[key]=true;


void skeyup(int key, int x, int y)

    skeystates[key]=false;


void key_func(void)

    if (keystates['z'])
    
        if(skeystates[GLUT_KEY_UP])zoomlvl+=1.f;
        if(skeystates[GLUT_KEY_DOWN])zoomlvl-=1.f;
        if(zoomlvl<-100.0f)zoomlvl=-100.f;
        if(zoomlvl>-5.f)zoomlvl=-5.f;
    
    else
    
        if(skeystates[GLUT_KEY_UP])camy-=1.f;
        if(skeystates[GLUT_KEY_DOWN])camy+=1.f;
        if(skeystates[GLUT_KEY_LEFT])camx+=1.f;
        if(skeystates[GLUT_KEY_RIGHT])camx-=1.f;
    


void render_p(us bot)

    glColor3f(cubers[bot].r,cubers[bot].g,cubers[bot].b);
    glBegin(GL_QUADS);
    glVertex2f(cubers[bot].size,cubers[bot].size);
    glVertex2f(cubers[bot].size,-cubers[bot].size);
    glVertex2f(-cubers[bot].size,-cubers[bot].size);
    glVertex2f(-cubers[bot].size,cubers[bot].size);
    glEnd();


void process_cubers(void)

    for(us i=0;i<totalbots;i++)
        if(cubers[i].coold==0)
            cubers[i].move();
            cubers[i].trans++;
            if(cubers[i].trans==20)
                cubers[i].trans=0;
                cubers[i].coold=50;
                if(cubers[i].age<100)
                    cubers[i].size+=0.025f;
                
                else if(cubers[i].age==150)
                    cubers[i].deliver(i);
                
                cubers[i].dir=rand()%8;
                cubers[i].age+=10;
            
        
        else cubers[i].coold--;
    

    for(us i=0;i<totalbots;i++)
    
        glPushMatrix();
        glTranslatef(cubers[i].x,cubers[i].y,cubers[i].z);
        render_p(i);
        glPopMatrix();
    


void display(void)

    key_func();
    glClearColor(0.6f,0.6f,0.6f,1.f);
    glClear (GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    gluPerspective(60, w / h,1.f,100.f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(camx,camy,zoomlvl);

    process_cubers();
    glutSwapBuffers();


void timer(int extra)

    glutPostRedisplay();
    glutTimerFunc(33, timer, 0);


int main (int argc, char **argv) 

    initkeys();
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize (640, 480);
    glutInitWindowPosition (0, 0); 
    glutCreateWindow ("opengl 1");
    glutDisplayFunc(display);
    glutKeyboardFunc(p_keys);
    glutKeyboardUpFunc(keyup);
    glutSpecialFunc(sp_keys);
    glutSpecialUpFunc(skeyup);
    glutTimerFunc(0, timer, 0);
    glutMainLoop();
    return 0;

您正在模拟循环中绘图。这会将其分成两个循环,然后 sim 然后绘制。

【讨论】:

另外,为了将来参考,我尝试对我的代码做同样的事情。似乎所有必须做的就是将 glpushmatrix 移动到循环的末尾而不是最开始,从而产生相同的结果。【参考方案2】:

图形渲染的工作方式(OpenGL 或其他方式)是它只保证两个三角形之间的“良好”接缝,如果您将它们渲染为同一个三角形条带的一部分,则它们沿某个边缘“完全”对齐,相同 (顶点缓冲区、索引缓冲区)模型对,或将三角形组合成单个渲染单元的其他构造。

当您渲染“四边形”时,您实际上是在渲染 2 个三角形的三角形条带,因此两个三角形之间的接缝看起来不错。

当您渲染两个沿某个边缘对齐的单独四边形时,该边缘可能看起来很糟糕。抗锯齿可以帮助稍微解决这个问题,但如果您想消除接缝处的撕裂,最终您需要使用单个渲染单元。

该图显示了在网格中渲染的四个四边形(八个三角形)。对角线在四边形内,因此没有任何撕裂,但是由于四边形都是单独渲染的,因此它们的接缝处会撕裂。

【讨论】:

感谢您的回复 timothy,我了解四边形是如何渲染的,但我有一种直觉,您不明白我遇到的问题。我遇到的问题不是边缘看起来很糟糕,而是矩形的短暂的、瞬间的错误定位。在很短的时间内,您可以看到所有矩形都聚集在一起(但或多或少,显然不在同一位置),并且在一帧之后(也许?很难说)它们到达指定的坐标。对我来说,当我将它们中的 4 个对齐时,矩形看起来很完美,但我想我错过了一些东西......

以上是关于opengl 微小的渲染故障,需要帮助和提示的主要内容,如果未能解决你的问题,请参考以下文章

Android OpenGLES2.0(十五)——利用EGL后台处理图像

Opengl:2d HUD 超过 3D

使用 OpenGL 渲染位数组

QT5提示can not find -lGL的解决方法

镜面高光故障 OpenGL

使用 OpenGL C++ 渲染到纹理