2011-03-25 18 views
1

我正在嘗試編寫一個使用opengl和cg編寫着色器的基本卷呈現器。我將我的傳遞函數放在一維紋理中,並在片段着色器中用於依賴紋理查找。我的問題是,當我嘗試啓用對應於該1D紋理的參數時,出現openGL錯誤。使用CG和openGL使用統一的1D紋理參數獲取錯誤

我的代碼很雜亂;現在它基本上是從「實時體積渲染」和「CG用戶手冊」中取得的代碼混搭。

C文件:

#include <stdio.h> 
#include <stdlib.h> 
#include <GL/glut.h> 
#include <Cg/cg.h> 
#include <Cg/cgGL.h> 

static CGcontext myCgContext; 
static CGprofile myCgVertexProfile, 
        myCgFragmentProfile; 
static CGprogram myCgVertexProgram, 
        myCgFragmentProgram; 

static const char *myProgramName = "first_volumetric_renderer", 
        *myVertexProgramFileName = "fvr_vertex.cg", 
        *myVertexProgramName = "fvr_vertex", 
        *myFragmentProgramFileName = "fvr_fragment.cg", 
        *myFragmentProgramName = "fvr_fragment"; 

static CGparameter first_texture, second_texture, transfer_function; 

#define XDIM 256 
#define YDIM 256 
#define ZDIM 256 
#define TRANSFER_RESOLUTION 256 
static GLubyte raw_data[XDIM][YDIM][ZDIM]; 
static GLubyte transfer[TRANSFER_RESOLUTION][4]; 
static GLuint transfer_name; 
static GLuint x_textures[XDIM], y_textures[YDIM], z_textures[ZDIM]; 


static void checkForCgError(const char *situation); 

/* print any errors if we get them */ 
void check_gl_error(const char * where){ 
    GLenum error = glGetError(); 
    if(error != GL_NO_ERROR){ 
    printf("openGL Error : %s : %s\n", where, gluErrorString(error)); 
    exit(1); 
    } 
} 

long int file_length(FILE *f){ 
    long int pos = ftell(f); 
    fseek(f, 0, SEEK_END); 
    long int result = ftell(f); 
    fseek(f, pos, SEEK_SET); 
    return result; 
} 

void get_volume_data(const char *filename){ 
    FILE *in = fopen(filename, "r"); 
    if(in == NULL) { 
    printf("opening '%s' to get volume data failed, exiting...\n", filename); 
    exit(1); 
    } 
    long int length = file_length(in); 
    if(length != XDIM*YDIM*ZDIM){ 
    printf("the file does not contain a volume of the correct dimensions\n"); 
    exit(1); 
    } 
    size_t res = fread((char *)raw_data, 1, length, in); 
    if(res < length) printf("error reading in file\n"); 

    fclose(in); 
} 


void create_textures(){ 
    glEnable(GL_TEXTURE_2D); 

    // reserve texture identifiers 
    glGenTextures(XDIM, x_textures); 
    glGenTextures(YDIM, y_textures); 
    glGenTextures(ZDIM, z_textures); 

    // set texture properties 
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); 
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

    // generate slices in X 
    { 
    int x,y,z; 
    GLubyte x_slice[ZDIM][YDIM]; 
    for(x=0;x < XDIM; x++){ 
     for(y=0;y < YDIM; y++){ 
    for(z=0;z < ZDIM; z++){ 
     x_slice[z][y] = raw_data[x][y][z]; 
    } 
     } 
     GLuint texname = x_textures[x]; 
     glBindTexture(GL_TEXTURE_2D, texname); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, ZDIM, YDIM, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, x_slice); 
    } 
    } 

    // generate slices in Y 
    { 
    int x,y,z; 
    GLubyte y_slice[XDIM][ZDIM]; 
    for(y=0;y < YDIM; y++){ 
     for(x=0;x < XDIM; x++){ 
    for(z=0;z < ZDIM; z++){ 
     y_slice[x][z] = raw_data[x][y][z]; 
    } 
     } 
     GLuint texname = y_textures[y]; 
     glBindTexture(GL_TEXTURE_2D, texname); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, XDIM, ZDIM, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, y_slice); 
    } 
    } 

    // generate slices in Z 
    { 
    int x,y,z; 
    GLubyte z_slice[XDIM][YDIM]; 
    for(z=0;z < ZDIM; z++){ 
     for(y=0;y < YDIM; y++){ 
    for(x=0;x < XDIM; x++){ 
     z_slice[x][y] = raw_data[x][y][z]; 
    } 
     } 
     GLuint texname = z_textures[z]; 
     glBindTexture(GL_TEXTURE_2D, texname); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, XDIM, YDIM, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, z_slice); 
    } 
    } 
} 

void DrawSliceStack_NegativeZ(int numSlices){ 
    double dZPos = -1.0; 
    double dZStep = 2.0/((double)numSlices); 

    int slice; 
    for(slice = 0;slice < numSlices;slice++){ 
    double dZPosTex = (ZDIM * (dZPos + 1.0)/2.0); 
    int nTexIdx = (int)dZPosTex; 
    double dAlpha = dZPosTex - (double)nTexIdx; 

    check_gl_error("in slice-drawing function, before cg-stuff"); 

    cgGLSetTextureParameter(first_texture, z_textures[nTexIdx]); 
    checkForCgError("setting first texture"); 
    check_gl_error("1"); 
    cgGLEnableTextureParameter(first_texture); 
    checkForCgError("enabling first texture"); 
    check_gl_error("2"); 
    cgGLSetTextureParameter(second_texture, z_textures[nTexIdx + 1]); 
    checkForCgError("setting second texture"); 
    check_gl_error("3"); 
    cgGLEnableTextureParameter(second_texture); 
    checkForCgError("enabling second texture"); 
    check_gl_error("4"); 
    cgGLSetTextureParameter(transfer_function, transfer_name); 
    checkForCgError("setting transfer function"); 
    check_gl_error("5"); 
    cgGLEnableTextureParameter(transfer_function); 
    checkForCgError("enabling transfer function"); 
    check_gl_error("before updating parameters"); 
    cgUpdateProgramParameters(myCgFragmentProgram); 
    checkForCgError("updating parameters"); 

    check_gl_error("before drawing a slice"); 
    glBegin(GL_QUADS); 
    glTexCoord3d(0.0, 0.0, dAlpha); 
    glVertex3d(-1.0, -1.0, dZPos); 
    glTexCoord3d(0.0, 1.0, dAlpha); 
    glVertex3d(-1.0, 1.0, dZPos); 
    glTexCoord3d(1.0, 1.0, dAlpha); 
    glVertex3d(1.0, 1.0, dZPos); 
    glTexCoord3d(1.0, 0.0, dAlpha); 
    glVertex3d(1.0, -1.0, dZPos); 
    glEnd(); 
    check_gl_error("after drawing a slice"); 

    dZPos += dZStep; 

    cgGLDisableTextureParameter(first_texture); 
    checkForCgError("disabling first texture"); 
    cgGLDisableTextureParameter(second_texture); 
    checkForCgError("disabling second texture"); 
    cgGLDisableTextureParameter(transfer_function); 
    checkForCgError("disabling transfer function"); 

    } 
} 

void create_transfer_texture(){ 
    glEnable(GL_TEXTURE_1D); 

    // create the raw data 
    int i; 
    for(i = 0; i < TRANSFER_RESOLUTION; i++){ 
    if(i < 50) { 
     transfer[i][0] = (GLubyte)0; 
     transfer[i][1] = (GLubyte)0; 
     transfer[i][2] = (GLubyte)0; 
     transfer[i][3] = (GLubyte)0; 
    } 
    else { 
     transfer[i][0] = (GLubyte)255; 
     transfer[i][1] = (GLubyte)255; 
     transfer[i][2] = (GLubyte)255; 
     transfer[i][3] = (GLubyte)i; 
    } 
    } 

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    glGenTextures(1, &transfer_name); 
    glBindTexture(GL_TEXTURE_3D, transfer_name); 
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, TRANSFER_RESOLUTION, 0, GL_RGBA, GL_UNSIGNED_BYTE, transfer); 
    check_gl_error("creating transfer texture"); 
} 

static void checkForCgError(const char *situation) 
{ 
    CGerror error; 
    const char *string = cgGetLastErrorString(&error); 

    if (error != CG_NO_ERROR) { 
    printf("%s: %s: %s\n", 
     myProgramName, situation, string); 
    if (error == CG_COMPILER_ERROR) { 
     printf("%s\n", cgGetLastListing(myCgContext)); 
    } 
    exit(1); 
    } 
} 

void init_CG(){ 
    // copy-pasted straight from one of the CG examples 
    myCgContext = cgCreateContext(); 
    checkForCgError("creating context"); 
    cgGLSetDebugMode(CG_FALSE); 
    cgSetParameterSettingMode(myCgContext, CG_DEFERRED_PARAMETER_SETTING); 


    myCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); 
    cgGLSetOptimalOptions(myCgFragmentProfile); 
    checkForCgError("selecting fragment profile"); 

    myCgFragmentProgram = 
    cgCreateProgramFromFile(
     myCgContext,    /* Cg runtime context */ 
     CG_SOURCE,     /* Program in human-readable form */ 
     myFragmentProgramFileName, /* Name of file containing program */ 
     myCgFragmentProfile,  /* Profile: OpenGL ARB vertex program */ 
     myFragmentProgramName,  /* Entry function name */ 
     NULL);      /* No extra compiler options */ 
    checkForCgError("creating fragment program from file"); 
    cgGLLoadProgram(myCgFragmentProgram); 
    checkForCgError("loading fragment program"); 

    first_texture = cgGetNamedParameter(myCgFragmentProgram, "text0"); 
    checkForCgError("could not get 'texture0'"); 
    second_texture = cgGetNamedParameter(myCgFragmentProgram, "text1"); 
    checkForCgError("could not get 'texture1'"); 
    transfer_function = cgGetNamedParameter(myCgFragmentProgram, "transfer_function"); 
    checkForCgError("could not get 'transfer_function'"); 

    check_gl_error("initializing CG"); 
} 

void reshape(int w, int h) 
{ 
    if (h == 0) h = 1; 
    glViewport(0, 0,w,h); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(-2, 2, -2, 2, -2, 2); // use orthographic projection 
    glMatrixMode(GL_MODELVIEW); 
} 

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


    /* cgGLBindProgram(myCgVertexProgram); 
    checkForCgError("binding vertex program"); 

    cgGLEnableProfile(myCgVertexProfile); 
    checkForCgError("enabling vertex profile");*/ 

    cgGLBindProgram(myCgFragmentProgram); 
    checkForCgError("binding fragment program"); 

    cgGLEnableProfile(myCgFragmentProfile); 
    checkForCgError("enabling fragment profile"); 

    check_gl_error("before entering slice-drawing function"); 
    DrawSliceStack_NegativeZ(ZDIM * 2); 

    /*cgGLDisableProfile(myCgVertexProfile); 
    checkForCgError("disabling vertex profile");*/ 

    cgGLDisableProfile(myCgFragmentProfile); 
    checkForCgError("disabling fragment profile"); 

    glutSwapBuffers(); 

    check_gl_error("Finishing 'display()'"); 
} 

void keyboard(unsigned char c, int x, int y){ 
} 

void init_glut(int argc, char** argv){ 
    glutInitWindowSize(400, 400); 
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 
    glutInit(&argc, argv); 

    glutCreateWindow(myProgramName); 
    glutDisplayFunc(display); 
    glutKeyboardFunc(keyboard); 
    glutReshapeFunc(reshape); 

    glClearColor(1.0, 0.0, 0.0, 0.0); /* Black background */ 
} 

int main(int argc, char **argv){ 
    init_glut(argc, argv); 
    init_CG(); 
    get_volume_data("aneurism.raw"); 
    create_textures(); 
    create_transfer_texture(); 

    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

    glutMainLoop(); 
    return 0; 
} 

片段着色器(fvr_fragment.cg):

float4 fvr_fragment(half3 texUV : TEXCOORD0, 
       uniform sampler2D text0, 
       uniform sampler2D text1, 
       uniform sampler1D transfer_function) : COLOR 
    { 
     half tex0 = tex2D(text0, texUV.xy); 
     half tex1 = tex2D(text1, texUV.xy); 

     half interp = lerp(tex0, tex1, texUV.z); 
     float4 result = tex1D(transfer_function, interp); 

     return result; 
    } 

the volume data

當運行時,該程序輸出:

openGL Error : before updating parameters : invalid operation 

鋰ne導致錯誤,我發現感謝我的特設打印調試,是:

cgGLEnableTextureParameter(transfer_function); 

任何想法?

回答

2

你的錯誤是在這裏

glBindTexture(GL_TEXTURE_3D, transfer_name); 

它應該閱讀

glBindTexture(GL_TEXTURE_1D, transfer_name); 
+0

這就是我得到了拷貝和粘貼代碼 – Bwmat 2011-03-31 16:35:17