0

I found a wonderful volume rendering tutorial on the internet: volume rendering tutorial . The sample code is written in Windows and since I am working on a Mac, I tried to write my own code according to my understanding. For now, my program just arranges the 2D frame from -1 to 1 in Z axis without applying alpha and blend. So if everything goes well, I should be able to see the first slice. However, when I run the program, I get something weird.

My code:

//
//  VolumeRendering.cpp
//  Volume_Rendering
//
//  Created by HOBBY on 4/5/14.
//  Copyright (c) 2014 Yihao Jiang. All rights reserved.
//
#include <GLTools.h>
#include <GL/glew.h>
#include <Opengl/gl.h>
#include <glut/glut.h>
#include <fstream>
#include "VolumeRendering.h"
#include <GLMatrixStack.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>

int m_uImageCount;
int m_uImageWidth;
int m_uImageHeight;
GLuint* m_puTextureIDs;

GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLFrame       cameraFrame;
GLFrustum     viewFrustum;
GLBatch       myBatch;
GLGeometryTransform    transformPipeline;
GLShaderManager        shaderManager;

void ChangeSize(int w, int h)
{
   glViewport(0, 0, w, h);
   GLdouble aspectRatio = (GLdouble)(w)/(GLdouble)(h);
   if (w <= h)
   {
       viewFrustum.SetOrthographic(-1.0f, 1.0f, -(1.0f/aspectRatio), 1.0f/aspectRatio, -1.0f, 1.0f);
   }
   else
   {
       viewFrustum.SetOrthographic(-1.0f, 1.0f, -(1.0f * aspectRatio), 1.0f * aspectRatio, -1.0f, 1.0f);
   }
   projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
   transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

}

void SetupRC()
{
   glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
   shaderManager.InitializeStockShaders();

   glEnable(GL_DEPTH_TEST);

   const char* filePath = "/Users/WensarHobby/Documents/Codes/workspace/Volume_Rendering/Volume_Rendering/head256x256x109";
   if(!InitTextures2D(filePath))
   {
       printf("InitTexture error");
   }

}

bool InitTextures2D(const char* filePath)
{
    std::fstream myFile;
    myFile.open(filePath, std::ios::in | std::ios::binary);

    m_uImageCount = 109;
    m_uImageWidth = 256;
    m_uImageHeight = 256;

    // Holds the texuture IDs
    m_puTextureIDs = new GLuint[m_uImageCount];

    // Holds the luminance buffer
    char* chBuffer = new char[m_uImageWidth * m_uImageHeight];
    char* chRGBABuffer = new char[m_uImageWidth * m_uImageHeight * 4];
    glGenTextures(m_uImageCount, (GLuint*)m_puTextureIDs);

    // Read each frames and construct the texture
    for( int nIndx = 0; nIndx < m_uImageCount; ++nIndx )
    {
        // Read the frame
        myFile.read(chBuffer, m_uImageWidth*m_uImageHeight);

        // Set the properties of the texture.
        glBindTexture( GL_TEXTURE_2D, m_puTextureIDs[nIndx] );
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_uImageWidth, m_uImageHeight , 0,
                 GL_LUMINANCE, GL_UNSIGNED_BYTE,(GLvoid *) chBuffer);
        glBindTexture( GL_TEXTURE_2D, 0 );
    }

    delete[] chBuffer;
    delete[] chRGBABuffer;
    return true;
}

void SpecialKeys(int key, int x, int y)
{
    if(key == GLUT_KEY_UP)
    {}

    if (key == GLUT_KEY_DOWN)
    {

    }

    if (key == GLUT_KEY_LEFT)
    {

    }

    if (key == GLUT_KEY_RIGHT)
    {

    }

    glutPostRedisplay();
}

void RenderScene(void)
{
    static GLfloat vLightPos [] = { 1.0f, 1.0f, 0.0f };
    static GLfloat vWhite [] = { 1.0f, 1.0f, 1.0f, 1.0f };

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


    modelViewMatrix.PushMatrix();
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.MultMatrix(mCamera);

    for(int nIndx=0; nIndx <m_uImageCount;++nIndx)
    {
        glBindTexture(GL_TEXTURE_2D, m_puTextureIDs[nIndx]);
        MakeQuads(nIndx);
        glBindTexture(GL_TEXTURE_2D, m_puTextureIDs[nIndx]);

    }


    shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
                             transformPipeline.GetModelViewMatrix(),
                             transformPipeline.GetProjectionMatrix(),
                             vLightPos, vWhite, 0);
    myBatch.Draw();


    modelViewMatrix.PopMatrix();

    glutSwapBuffers();

}

void MakeQuads(int quads_index)
{
    myBatch.Begin(GL_QUADS, 4, 1);
    myBatch.Normal3f(0.0f, 0.0f, -1.0f);
    myBatch.MultiTexCoord2f(quads_index, 0.0f, 0.0f);
    myBatch.Vertex3f(-1.0f, -1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));

    myBatch.Normal3f(0.0f, 0.0f, -1.0f);
    myBatch.MultiTexCoord2f(quads_index, 1.0f, 0.0f);
    myBatch.Vertex3f(1.0f, -1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));

    myBatch.Normal3f(0.0f, 0.0f, -1.0f);
    myBatch.MultiTexCoord2f(quads_index, 0.0f, 1.0f);
    myBatch.Vertex3f(-1.0f, 1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));

    myBatch.Normal3f(0.0f, 0.0f, -1.0f);
    myBatch.MultiTexCoord2f(quads_index, 1.0f, 1.0f);
    myBatch.Vertex3f(1.0f, 1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
    myBatch.End();
}

void ShutdownRC(void)
{
    glDeleteTextures(m_uImageCount, (GLuint*)m_puTextureIDs);
}


int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(400, 400);
    glutCreateWindow("Volume_Rendering");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);

    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    SetupRC();

    glutMainLoop();
    ShutdownRC();
    return 0;

}

And this is my weird result: weird result

I am new to OpenGL and volume rendering, in my opinion, there should be something wrong with my use of the shader manager. But I am not so sure. Anyone can tell me where the problem is? Thank you very much.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
NJUHOBBY
  • 850
  • 3
  • 10
  • 30
  • this looks pretty typical first step debug for anything opengl or directx in my opinion haha. You should see if fiddling with your quad coordinates you don't get something better. this looks like some wrong vertice rotation order with face culling enabled. could be anything though. its already good you see blue ! – v.oddou Apr 14 '14 at 00:27
  • I'd recommend posting the shader code as well (I didn't spot anything obvious.) As @v.oddou said, this is not unusual for first renders with new code. I would also recommend temporarily knocking out all your texturing code, and focus on getting the geometry right (with fixed colors) first. – holtavolt Apr 14 '14 at 01:55
  • @v.oddou I did some test, I changed the orthographic projection to perspective projection, it seems work. So what's wrong with the use of setOrthographic function in my code? – NJUHOBBY Apr 14 '14 at 03:53
  • @holtavolt I did a lot of tests and now I am almost sure that the problem lies in the function MakeQuads(), more specifically the MultiTexCoord2f() function. If I just draw one frame on the screen and replace all quads_index with 0, it works. Now I am thinking how to draw several textures with one shader.... – NJUHOBBY Apr 14 '14 at 19:08

1 Answers1

1

Finally, I figure it out! I was right and the problem lies in function MultiTexCoord2f(). The first parameter of this function here should always be 0 rather than quads_index. No multitextures here!! The new code looks like this:

#include <GLTools.h>
#include <GL/glew.h>
#include <Opengl/gl.h>
#include <glut/glut.h>
#include <fstream>
#include "VolumeRendering.h"
#include <GLMatrixStack.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>

int m_uImageCount;
int m_uImageWidth;
int m_uImageHeight;
GLuint* m_puTextureIDs;

GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLFrame       cameraFrame;
GLFrame       objectFrame;
GLFrustum     viewFrustum;
GLBatch       myBatch;
GLGeometryTransform    transformPipeline;
GLShaderManager        shaderManager;

void ChangeSize(int w, int h)
{
    glViewport(0, 0, w, h);
    viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}    

void SetupRC()
{
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    shaderManager.InitializeStockShaders();

    glEnable(GL_DEPTH_TEST);

    const char* filePath =     "/Users/WensarHobby/Documents/Codes/workspace/Volume_Rendering/Volume_Rendering/head256x256x109";
    if(!InitTextures2D(filePath))
    {
        printf("InitTexture error");
    }

    cameraFrame.MoveForward(-7.0f);
}

bool InitTextures2D(const char* filePath)
{
    std::fstream myFile;
    myFile.open(filePath, std::ios::in | std::ios::binary);

    m_uImageCount = 109;
    m_uImageWidth = 256;
    m_uImageHeight = 256;

    // Holds the texuture IDs
    m_puTextureIDs = new GLuint[m_uImageCount];

    // Holds the luminance buffer
    char* chBuffer = new char[m_uImageWidth * m_uImageHeight];
    //char* chRGBABuffer = new char[m_uImageWidth * m_uImageHeight * 4];
    glGenTextures(m_uImageCount, m_puTextureIDs);

    // Read each frames and construct the texture
    for( int nIndx = 0; nIndx < m_uImageCount; ++nIndx )
    {
        // Read the frame
        myFile.read(chBuffer, m_uImageWidth*m_uImageHeight);

        // Set the properties of the texture.
        glBindTexture( GL_TEXTURE_2D, m_puTextureIDs[nIndx] );
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_uImageWidth, m_uImageHeight , 0,
                 GL_LUMINANCE, GL_UNSIGNED_BYTE,(GLvoid *) chBuffer);
        glBindTexture( GL_TEXTURE_2D, 0 );
    }

    delete[] chBuffer;
   // delete[] chRGBABuffer;
    return true;
}

void SpecialKeys(int key, int x, int y)
{
glutPostRedisplay();
}

void RenderScene(void)
{
    static GLfloat vLightPos [] = { 1.0f, 1.0f, 0.0f };
    static GLfloat vWhite [] = { 1.0f, 1.0f, 1.0f, 1.0f };

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


    modelViewMatrix.PushMatrix();
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.MultMatrix(mCamera);

    M3DMatrix44f mObjectFrame;
    objectFrame.GetMatrix(mObjectFrame);
    modelViewMatrix.MultMatrix(mObjectFrame);

    for(int nIndx=0; nIndx <m_uImageCount;++nIndx)
    {
        glBindTexture(GL_TEXTURE_2D, m_puTextureIDs[nIndx]);
        MakeQuads(nIndx);
        glBindTexture(GL_TEXTURE_2D, m_puTextureIDs[nIndx]);
        shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
                                 transformPipeline.GetModelViewMatrix(),
                                 transformPipeline.GetProjectionMatrix(),
                                 vLightPos, vWhite, 0);
        myBatch.Draw();
    }

    modelViewMatrix.PopMatrix();

    glutSwapBuffers();

}

void MakeQuads(int quads_index)
{
    myBatch.Begin(GL_QUADS, 4, 1);

    myBatch.Normal3f(0.0f, 0.0f, -1.0f);
    myBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    myBatch.Vertex3f(-1.0f, -1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
    //myBatch.Vertex3f(-1.0f, -1.0f, 1.0f);

    myBatch.Normal3f(0.0f, 0.0f, -1.0f);
    myBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    myBatch.Vertex3f(1.0f, -1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
    //myBatch.Vertex3f(1.0f, -1.0f, 1.0f);

    myBatch.Normal3f(0.0f, 0.0f, -1.0f);
    myBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
    myBatch.Vertex3f(1.0f, 1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
    //myBatch.Vertex3f(1.0f, 1.0f, 1.0f);

    myBatch.Normal3f(0.0f, 0.0f, -1.0f);
    myBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
    myBatch.Vertex3f(-1.0f, 1.0f, 1.0f - (GLfloat)(quads_index/m_uImageCount));
    //myBatch.Vertex3f(-1.0f, 1.0f, 1.0f);

    myBatch.End();
}

void ShutdownRC(void)
{
    glDeleteTextures(m_uImageCount, (GLuint*)m_puTextureIDs);
}


int main(int argc, char* argv[])
{    
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(400, 400);
    glutCreateWindow("Volume_Rendering");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);

    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    SetupRC();

    glutMainLoop();

    ShutdownRC();
    return 0;

}
NJUHOBBY
  • 850
  • 3
  • 10
  • 30