2013-04-04 139 views
1

我的問題與這個很接近:FBO and Render to renderbuffer。 我目前正試圖渲染一個簡單的三角形,像這個tutorial這樣的渲染緩衝區。我的程序是Igor Pro的一個插件,用於執行OpenGL的屏幕渲染。用FBO繪製到渲染緩衝區

不幸的是,當我試圖讀取像素值時,我只得到零。 我已經知道initBuffers函數有效,問題在於display函數。

1)我的代碼有什麼問題?

2)我想呈現一個頂點數據列表,而不使用即時模式。我以前曾經與維也納國際組織進行過實施。我可以重複使用該代碼嗎?

我的代碼如下:

/* 
RenderTriangle.cpp 
*/ 

#include "VC10\triangulation.h" 
#include "XOPStandardHeaders.h"   // Include ANSI headers, Mac headers, IgorXOP.h, XOP.h and XOPSupport.h 
#include <vector> 


// Prototypes 
HOST_IMPORT int main(IORecHandle ioRecHandle); 

// Global Variables 
const int windowSize = 512; 

int size,el_size; 
float* waveX=NULL; 
float* waveY=NULL; 
float* waveZ=NULL; 
GLuint framebuffer, renderbuffer; 

// Custom error codes 
#define OLD_IGOR 1 + FIRST_XOP_ERR 
#define NON_EXISTENT_WAVE 2 + FIRST_XOP_ERR 
#define REQUIRES_SP_OR_DP_WAVE 3 + FIRST_XOP_ERR 

#pragma pack(2)  // All structures passed to Igor are two-byte aligned. 
typedef struct WaveParams { 
    waveHndl waveZ; 
    waveHndl waveY; 
    waveHndl waveX; 
    double result; 
} WaveParams, *WaveParamsPtr; 
#pragma pack()  // Restore default structure alignment 

// Prototypes of the OpenGL callbacks 
void initBuffers(void); 
void display(void); 
void readPixels(void); 

void initBuffers(void){ 

    GLenum status; 

    //Generate the fbo where we will bind a render buffer object 
    glGenFramebuffers(1,&framebuffer); 
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER,framebuffer); 

    //Generate render buffer object 
    glGenRenderbuffers(1,&renderbuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER,renderbuffer); 

    glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA8, windowSize, windowSize); 

    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); 

    status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 

    if (status != GL_FRAMEBUFFER_COMPLETE) 
    XOPNotice("Error Framebuffer Complete"); 
    else 
    XOPNotice("Framebuffer Complete"); 
} 

void display(void){//display a simple triangle 

    glViewport(0,0,windowSize,windowSize); 
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 
    glClearColor(1.0f, 0.0f, 0.0f,0.5f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 

    glBegin(GL_TRIANGLES);// Drawing Using Triangles 
    glColor3f(1.0f, 0.0f, 0.0f);glVertex3f(0.0f, 1.0f, 0.0f);// Top 
    glColor3f(1.0f, 0.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 0.0f);// Bottom Left 
    glColor3f(1.0f, 0.0f, 0.0f);glVertex3f(1.0f,-1.0f, 0.0f);// Bottom Right 
    glEnd();// Finished Drawing The Triangle 

    glFlush(); 

} 

// Idle callback function for OpenGL API 
void readPixels(void){ 

    //glBindFramebuffer(GL_FRAMEBUFFER, 0); 

    float* pixels = (float*)malloc(windowSize*windowSize*sizeof(float)); 
    glReadBuffer(GL_COLOR_ATTACHMENT0); 
    glReadPixels(0, 0, windowSize, windowSize, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); 

    waveHndl waveH; 
    char waveName[MAX_OBJ_NAME+1]; 
    DataFolderHandle dfH; 
    CountInt dimensionSizes[MAX_DIMENSIONS+1]; 
    float* wp; 
    IndexInt p; 
    double offset, delta; 
    int err; 
    strcpy(waveName, "wave1"); 
    dfH = NULL; // Put wave in the current data folder 
    MemClear(dimensionSizes, sizeof(dimensionSizes)); 

    dimensionSizes[ROWS] = windowSize; // Make 1D wave with 100 points 
    dimensionSizes[COLUMNS] = windowSize; 

    if (MDMakeWave(&waveH, waveName, dfH, dimensionSizes, NT_FP32, 1)) 
    XOPNotice("Can't create wave when reading pixel values"); 

    wp = (float*)WaveData(waveH); // Get a pointer to the wave data 

    for(p = 0; p < windowSize*windowSize; p++) 
    *wp++ = pixels[p]; // Store point number in wave 



} 
void deleteBuffers(){ 
    glDeleteFramebuffers(1,&framebuffer); 
    glDeleteRenderbuffers(1,&renderbuffer); 
} 
// Main function for the XOP 
extern "C" int 
    RenderTriangle(WaveParamsPtr p) 
{ 
    //Pointers to the input waves 
    waveX=(float*)WaveData(p->waveX); 
    waveY=(float*)WaveData(p->waveY); 
    waveZ=(float*)WaveData(p->waveZ); 

    //Creates the window 
    char *myargv [1]; 
    int myargc=1, windowHandle; 
    myargv [0]=strdup ("RenderTriangle"); 

    glutInit(&myargc,myargv); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_DEPTH | GLUT_RGB); 
    glutInitWindowSize(windowSize,windowSize); 
    windowHandle = glutCreateWindow("OpenGL"); 

    //Init glew library 
    glewInit(); 

    //Creates the fbo and render buffer object 
    initBuffers(); 

    display(); 

    readPixels(); 

    //Deletes the fbo and render buffer object 
    deleteBuffers(); 

    p->result = 1; 

    return 0; 
} 

static XOPIORecResult 
    RegisterFunction() 
{ 
    int funcIndex; 

    funcIndex = (int)GetXOPItem(0);   // Which function invoked ? 
    switch (funcIndex) { 
    case 0:         // y = RenderTriangle(w,x) (curve fitting function). 
    return (XOPIORecResult)RenderTriangle; // This function is called using the direct method. 
    break; 
    } 
    return 0; 
} 

/* XOPEntry() 

This is the entry point from the host application to the XOP for all 
messages after the INIT message. 
*/ 
extern "C" void 
    XOPEntry(void) 
{ 
    XOPIORecResult result = 0; 

    switch (GetXOPMessage()) { 
    case FUNCADDRS: 
    result = RegisterFunction(); // This tells Igor the address of our function. 
    break; 
    } 
    SetXOPResult(result); 
} 

/* main(ioRecHandle) 

This is the initial entry point at which the host application calls XOP. 
The message sent by the host must be INIT. 
main() does any necessary initialization and then sets the XOPEntry field of the 
ioRecHandle to the address to be called for future messages. 
*/ 
HOST_IMPORT int 
    main(IORecHandle ioRecHandle) 
{ 
    XOPInit(ioRecHandle);       // Do standard XOP initialization. 
    SetXOPEntry(XOPEntry);       // Set entry point for future calls. 

    if (igorVersion < 600) { 
    SetXOPResult(OLD_IGOR); 
    return EXIT_FAILURE; 
    } 

    SetXOPResult(0); 
    return EXIT_SUCCESS; 
} 

回答

1

您需要一個可用的OpenGL上下文才能運行,而您不需要創建一個!您將GLUT用作框架,但GLUT僅在調用glutCreateWindow時才創建渲染上下文。在此之前,你根本沒有活躍的RC,其餘的都無法工作。

也許Igor本身在某個時候創建​​了一個OpenGL上下文,而你正在貶低那個。

而不是使用GLUT你應該使用系統級的API來

  1. 店當前上下文狀態(如上下文在當前線程是活動的,如果是這樣,上下文句柄)

  2. 如果尚未完成:創建一個離屏渲染方面給你的插件(與宗教組織一起使用p緩衝器或不可見的窗口)

  3. 用自己的語境做你的渲染

  4. 恢復上下文狀態保存在1

1

我建議另一個教程:http://www.songho.ca/opengl/gl_fbo.html

但對於你的代碼:

這將是simplier來直接呈現紋理。這樣就沒有理由使用glReadPixels。整個操作將更快,更容易實施。

創建空紋理,並通過glFramebufferTexture2D將其添加到FBO,並在渲染後在紋理中獲得結果。

0

同樣地,在這裏是使用renderbuffers一個例子。

How to render offscreen on OpenGL?

1)創建上下文 2)創建FBO(存儲用於顏色,深度,模板)和結合 3)畫出 4)回讀(根據2))

我不相信如果說整個操作會更快,更容易用紋理實現,那是否正確。這一切都取決於我們想要做什麼(glReadPixels是同步的)。

相關問題