我在互联网上找到了一个很棒的体积渲染教程:
volume rendering tutorial
。该示例代码是用Windows编写的,并且由于我在Mac上工作,因此我尝试根据自己的理解编写自己的代码。现在,我的程序只是在不应用alpha和blend的情况下将2D帧在Z轴上从-1排列到1。因此,如果一切顺利,我应该能够看到第一个片段。但是,当我运行该程序时,我得到了一些奇怪的东西。
我的代码:
//
// 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;
}
这是我的怪异结果:
我认为我是OpenGL和体积渲染的新手,我使用着色器管理器应该有问题。但是我不确定。有人可以告诉我问题出在哪里吗?非常感谢你。
最佳答案
最后,我知道了!我是对的,问题出在函数MultiTexCoord2f()上。此函数的第一个参数此处应始终为0,而不是quads_index。这里没有多重纹理!!新代码如下所示:
#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;
}