Laboratorul 2

Ray casting

Ray casting reprezintă implementarea modelului teoretic de redare directă.

Figura 1

Concepte teoretice

Pașii algoritmului

Pentru fiecare rază (pixel):

  1. Calculează direcția razei care pleacă de la observator și trece prin centrul pixelului
  2. Calculează pozițiile de eșantionare de-a lungul razei
  3. Calculează valorile eșantioanelor prin interpolare triliniară
  4. Calculează gradientul în fiecare poziție de eșantionare, prin interpolare triliniară
  5. Determină o culoare și o opacitate pentru fiecare eșantion, folosind funcții de transfer și calcule de iluminare
  6. Acumulează culoarea (și opacitatea) în fiecare punct de eșantionare

Implementare

  • Volumul încadrator al volumului de date, în spațiul obiect, este un cub cu coordonatele vârfurilor în intervalul (0,0,0) - (1,1,1)
  • Astfel, coordonatele textură asociate vârfurilor cubului sunt chiar coordonatele vârfurilor
  • Asociem vârfurilor culorile (R,G,B) corespunzătoare coordonatelor vârfurilor, si rasterizăm fețele cubului
    Mesh* lab2::createCube(const char* name)
    {
        vector<VertexFormat> vertices
        {
            VertexFormat(glm::vec3(0, 0, 0), glm::vec3(0, 0, 0)),
            VertexFormat(glm::vec3(0, 0, 1), glm::vec3(0, 0, 1)),
            VertexFormat(glm::vec3(0, 1, 0), glm::vec3(0, 1, 0)),
            ...
        }
    }
  • Atunci culorile punctelor reprezintă chiar coordonatele lor. În Figura 2, stânga, se văd fețele față ale cubului și în dreapta, fețele spate:
    • punctele de pe fețele față sunt punctele în care razele intră în volum
    • punctele de pe fețele spate sunt punctele în care razele ies din volum

Figura 2

Etapa 1

Determinarea punctelor de ieșire ale razelor din volum

  • Se desenează într-un framebuffer (nu în cel default)
    frameBuffer->Bind(); 
  • Se rasterizează fețele din spate ale cubului încadrator
    glEnable(GL_CULL_FACE);
    glCullFace(GL_FRONT);
    RenderMesh(meshes["cube"], shaders["BackFaceShader"], model_matrix);
    glDisable(GL_CULL_FACE);
  • Fiecare pixel al acestei imagini conține adresa (salvată prin culoare) punctului de ieșire din volum al razei care trece prin acel pixel.

Etapa 2

Determinarea punctelor de intrare ale razelor în volum

  • Se desenează în buffer-ul default
    FrameBuffer::BindDefault();
  • Se rasterizează fețele din față ale cubului încadrator (fie prin enable la back-face culling, fie fără niciun fel de culling)
  • Fiecare pixel al imaginii obținute reprezintă adresa punctului de intrare

Calculul culorilor razelor (Ray Casting)

  • Se trimite către fragment shader textura 3D care conține volumul de date:
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_3D, volumeTexture);
    glUniform1i(glGetUniformLocation(shader->program, "VolumeTex"), 1);
  • Se trimite către fragment shader textura 1D care conține funcția de transfer:
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_1D, tfTexture);
    glUniform1i(glGetUniformLocation(shader->program, "TransferFunc"), 2);
  • Se calculează direcția razei pixelului curent (diferența între punctul de ieșire și punctul de intrare în volum)
    • Punctul de ieșire se obține din valoarea texelului corespunzător pixelului curent (folosind textura framebuffer-ului din Etapa 1)
      • Textura din Etapa 1 se trimite către shader-ul din Etapa 2
        int textureLoc = shader->GetUniformLocation("ExitPoints");
        glUniform1i(textureLoc, 0);
        frameBuffer->BindTexture(0, GL_TEXTURE0);
      • În vertex shader, coordonatele vârfurilor cubului sunt transformate prin MVP în coordonate NDC, cuprinse între (-1,-1,-1) și (1,1,1)
      • Coordonata în NDC a fiecărui vârf e transmisă către fragment shader ca o coordonată de textură
        ExitPointCoord = gl_Position;
      • ExitPointCoord se folosește în fragment shader pentru accesarea texturii create în prima etapă.
      • pentru indexarea texturii se obțin coordonatecoordonate ExitFragCoord cu valori cuprinse între 0 și 1:

  • Punctul de intrare se obține din culoarea fragmentului curent (în VS):
    EntryPoint = v_color;
  • Se calculează versorul razei, lungimea acesteia și vectorul cu care se înaintează pe rază (de la un punct de eșantionare la altul)
  • Pentru fiecare eșantion (pornind de la punctul de intrare al razei în volum):
    • Se calculează valoarea scalară din volum (folosind textura 3D VolumeTex) și coordonata de textură dată de poziția eșantionului
    • Se calculează o culoare folosind textura 1D TransferFunc și coordonata de textură dată de valoarea scalară anterior obținută
    • Se modulează opacitatea și culoarea
    • Se realizează compunere din față în spate
      colorAcum.rgb += (1.0 - colorAcum.a) * colorSample.rgb;
      colorAcum.a += (1.0 - colorAcum.a) * colorSample.a;
    • Se verifică dacă raza curentă a ieșit din volum sau dacă opacitatea acumulată a ajuns la 1

Cerințe laborator

  1. Să se completeze valoarea variabilei frag_color pentru a fi transmisă mai departe către fragment shader (în VertexShader_backface.glsl)
  2. Să se calculeze corect culoarea out_color ca să se afișeze fețele spate ale volumului încadrator (în FragmentShader_backface.glsl)
  3. Să se trimită către fragment shader EntryPoint și ExitPointCoord (în VertexShader_raycasting.glsl)
  4. Să se calculeze coordonatele ExitFragCoord pentru accesarea texturii ExitPoints (în FragmentShader_raycasting.glsl)
  5. Să se calculeze ExitPoint - punctul de ieșire al razei din volum
  6. Să se calculeze direcția razei
  7. Să se calculeze vectorul cu care se înaintează pe rază (de la punctul de eșantionare curent la următorul)
  8. Să se calculeze valoarea scalară a eșantionului curent (în funcție de textura VolumeTex și de coordonata de textură voxelCoord)
  9. Să se calculeze culoarea eșantionului curent (în funcție de textura TransferFunc și de coordonata de textură dată de valoarea scalară curentă)
  10. Să se actualizeze poziția eșantionului
  11. Să se actualizeze lungimea parcursă pe rază

Demo

vdvac/lab2.txt · Last modified: 2024/03/25 15:41 by anca.morar
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0