我的問題與這個很接近: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;
}