Ошибка шейдера фрагмента нечетной строки OpenGL: не рисование

Я пишу приложение, которое отображает каждый кадр в стереоскопическом 3D с чередованием. Чтобы это произошло, я пишу два фрагментных шейдера: один для рендеринга нечетных строк кадра левого глаза, а другой для рендеринга четных рядов пикселей правого кадра.

Я использовал встроенное в OSX приложение OpenGL Shader Builder, и мне удалось успешно отобразить каждую нечетную строку как зеленую: OpenGL Shader Builder  шейдер фрагмента нечетной строки

Как видите, код фрага, который я использую, выглядит так:

    void main(){
        if ( mod(gl_FragCoord.y - 0.5, 2.0) == 1.0){
            gl_FragCoord = vec4(0.0, 1.0, 0.0, 1.0);
        }
    }

Тем не менее, я написал небольшое приложение OpenGL для тестирования этого шейдера (кстати, это NVIDIA OpenGL 2.1, OSX 10.6.8):

    #include <iostream>
    #include <stdio.h>


    #ifdef __APPLE__
    #include <OpenGL/gl.h>
    #include <OpenGL/glu.h>
    #include <GLUT/glut.h>


    void DrawGLScene(){
      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

      glFlush();
      glutSwapBuffers();
    }


    void Shading(){
      //Fragment shader we want to use
      GLuint oddRowShaderId = glCreateShader(GL_FRAGMENT_SHADER);
      std::cout << "Creating the fragment shader with id " << oddRowShaderId << std::endl;

      const GLchar *source[] = 
      { "void main(){   \n",
        "  if (mod(gl_FragCoord.y-0.5, 2.0) == 0.0){\n",
        "    gl_FragColor = vec4( 0.0, 1.0, 0.0, 1.0 );\n",
        //"    gl_BackColor = vec4( 0.0, 1.0, 0.0, 1.0 );\n"
        "  }\n",
        "}\n"
      };

      std::cout << "Shader source:\n" << source[0] << source[1] << source[2] << source[3] <       < source[4] << std::endl;


      std::cout << "Gathering shader source code" << std::endl;
      glShaderSource(oddRowShaderId, 1, source, 0);

      std::cout << "Compiling the shader" << std::endl;
      glCompileShader(oddRowShaderId);

      std::cout << "Creating new glCreateProgram() program" << std::endl;
      GLuint shaderProgramId = glCreateProgram();    //Shader program id

      std::cout << "Attaching shader to the new program" << std::endl;
      glAttachShader(shaderProgramId, oddRowShaderId); //Add the fragment shader to the         program

      std::cout << "Linking the program " << std::endl;
      glLinkProgram(shaderProgramId);                //Link the program


      std::cout << "Using the shader program for rendering" << std::endl;
      glUseProgram(shaderProgramId);                  //Start using the shader
    }

    void keyboard(int key, int x, int y){
      switch(key){
      case 's':
        Shading();
        break;
      case 'q':
        exit(0);
        break;
      }

    }

    void idleFunc(){
      glutPostRedisplay();        //Redraw the scene.
    }

    int main(int argc, char** argv){
      glutInit(&argc, argv);
      glutInitWindowPosition(100, 100);
      glutInitWindowSize(1000,1000);
      glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
      glutCreateWindow("anaglyph test");
      glutDisplayFunc(DrawGLScene);
      glutSpecialFunc(keyboard);
      glutIdleFunc(idleFunc);

      glutMainLoop();
    }

Вот результат, который я получаю при запуске кода: Error OutputУ меня такое чувство, что я не компилирую и glUsePrograming фрагментный шейдер корректно.


person a10y    schedule 14.11.2012    source источник
comment
Вы не проверяете ошибки при компиляции и ссылке шейдера, что нехорошо. Вы должны использовать glGetShaderiv/glGetProgramiv для запроса GL_COMPILE_STATUS и GL_LINK_STATUS после каждой компиляции и после связывания, и если они не возвращаются как TRUE, используйте glGetShaderInfoLog/glGetProgramInfoLog, чтобы узнать, на что он жалуется. Также я не рекомендую проводить тесты на равенство для чисел с плавающей запятой, так как могут возникнуть проблемы с округлением. Посмотрите, сможете ли вы воспроизвести ==1.0 с помощью сравнения больше/меньше, которое терпимо к незначительным ошибкам округления.   -  person Tim    schedule 14.11.2012
comment
спасибо! Я реализовал эти функции сейчас и обнаружил, что это проблема компиляции. Кажется, я исправил это, но теперь я получаю эту ошибку шины, когда пытаюсь запустить программу   -  person a10y    schedule 14.11.2012


Ответы (1)


Вы можете сэкономить немного производительности и получить некоторую совместимость, и это приведет к меньшей головной боли, используя 2-пиксельную текстурную маску (четные пиксели черные, нечетные - белые) и разместив ее поверх полноэкранных четырехугольников (у вас будет 2 из них: правый глаз и левый глаз). Используйте инвертированную маску или установите некоторое смещение координат на втором квадрате. В целом это будет выглядеть так:

(для визуализации добавлены перспектива и большие промежутки) введите здесь описание изображения

Поместите текстуру сцены (или что у вас есть) на квадрат и используйте цвет маски, чтобы отбросить фрагменты или прозрачность. Чтобы не использовать 2 g-буфера (память графического процессора), вы можете рендерить полную сцену для одного глаза в текстуре, а для другого в поле зрения и поверх него рендерить полноэкранный четырехугольник с текстурой первой сцены и маской прозрачности. Или сделайте их отдельными, если вам нужны два выхода.


Суть в том, что вы должны использовать маскирование вместо логических операций, основанных на координатах текстуры.

person JAre    schedule 14.11.2012