2017-09-24 9 views
5

Rysuję desenie, które mają szczegółowe piksele i często napotykają efekt Moire. Nie jestem dobry w cieniowaniu i nie jestem pewien, czy ten problem zostanie rozwiązany przez shadery. Nie znalazłem żadnego podstawowego, zrozumiałego i pełnego przykładu shaderów. Większość tutorialowych stron internetowych rozpoczyna program od środka, pomijając plik nagłówkowy!C++: Usuwanie efektu Moire z biblioteki OpenGL

To jest MWE mojego kodu. Czy możliwe jest złagodzenie lub usunięcie efektu Moire z niego?

#include <cmath> 
#include <vector> 

#ifdef __APPLE__ 
#include <GLUT/glut.h> 
#else 
#include <GL/glut.h> 
#endif 

const int w=640,h=480; 
float cam_angle=0.0f; 

void init() 
{ 
    GLfloat LightAmbient[] = { 0.2f, 0.2f, 0.2f, 1.0f }; 
    GLfloat LightDiffuse[] = { 0.5f, 0.5f, 0.5f, 1.0f }; 
    GLfloat LightPosition[] = { 5.0f, 5.0f, -10.0f, 1.0f }; 

    glClearColor(0.0, 0.0, 0.0, 0.0); 
    glShadeModel(GL_SMOOTH); 
    glEnable(GL_DEPTH_TEST); 
    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); 
    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); 
    glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); 
    glEnable(GL_LIGHT1); 
} 

void onDisplay() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective (90, float(w)/float(h), 0.01, 10000); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    const double pi=3.1415926; 
    double cam_x=2.0*cos(pi/4.0)*cos(cam_angle);; 
    double cam_y=2.0*sin(pi/4.0)*cos(cam_angle);; 
    double cam_z=2.0*sin(cam_angle); 
    gluLookAt(cam_x, cam_y, cam_z, 0, 0, 0, 0, 0, 1); 

    struct Point3D 
    { 
     double x, y, z; 
     unsigned char r, g, b, a=255; 
    }; 

    for(double r=0.5;r<=1.0;r+=0.03) 
    { 
     std::vector<Point3D> points; 
     for(int i=0;i<1000;i++) 
     { 
      double theta=double(i)/1000.0*pi*2.0; 
      Point3D p; 
      p.x=r*sin(theta); 
      p.y=r*cos(theta); 
      p.z=r; 
      p.r=128; 
      p.g=200; 
      p.b=50; 
      points.push_back(p); 
     } 
    // draw 
     glPushMatrix(); 
     glColor3ub(255,255,255); 
     glEnableClientState(GL_VERTEX_ARRAY); 
     glEnableClientState(GL_COLOR_ARRAY); 
     glVertexPointer(3, GL_DOUBLE, sizeof(Point3D), &points[0].x); 
     glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Point3D), &points[0].r); 
     // glPointSize(3.0); 
     glLineWidth(2.0); 
     glDrawArrays(GL_LINE_STRIP, 0, int(points.size())); 
     glDisableClientState(GL_VERTEX_ARRAY); 
     glDisableClientState(GL_COLOR_ARRAY); 
     glPopMatrix(); 
    } 

    glFlush(); 
    glutSwapBuffers(); 
} 

void Timer(int /*value*/) 
{ 
    cam_angle+=0.01f; 
    glutPostRedisplay(); 
    // 100 milliseconds 
    glutTimerFunc(100, Timer, 0); 
} 

int main(int argc, char** argv) 
{ 
    glutInit(&argc, argv); 
    glutInitWindowSize (w, h); 
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 
    glutInitWindowPosition (100, 100); 
    glutCreateWindow ("my window"); 
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 
    glEnable(GL_BLEND); 

    init(); 
    glutDisplayFunc(onDisplay); 
    Timer(0); 
    glutMainLoop(); 

    return 0; 
} 

Moire effect

+0

tej pętli 'dla (podwójne r = 0,5; R <= 1,0; R + = 0.03)' nie ma gwarancji uruchomienia taką samą ilość czasu, w zależności od kompilatora kompilatora ustawienia itp. Punkt zmienny nie jest dokładny, dlatego dodanie od 0,03 do 0,5 da niedokładną liczbę, a błąd narasta w każdej iteracji. Użyj liczby całkowitej jako liczników pętli, a nie zmiennoprzecinkowych. – PaulMcKenzie

+0

@ PaulMcKenzie. Nie ważne. Wszystkie scenariusze ostatecznie prowadzą do efektu Moire. – ar2015

+1

Jeśli wyświetlasz szczegółowe wzorce pikseli, o rozdzielczości i okresie lokalizacji w pobliżu rozdzielczości wyświetlania, wtedy tylko precyzyjnie dostrojona treść (np. NIE mające linii przecinających się, NIE posiadająca pikselowych "kroków" nachylenia ...) będzie wolna od Mora. Nie możesz rozwiązać problemu tak długo, jak trzymasz się precyzji pikseli i kilku kolorów. Rozwiązaniem (choć być może nie satysfakcjonującym) jest zmiana zawartości lub uruchomienie wygładzania i używanie efektu "wymycia" lub "zamazania", zarówno w porównaniu z wrażeniem "ostrym", jak i "precyzyjnym". pojedynczych kolorowych pikseli. – Yunnosch

Odpowiedz