OpenGL FBO渲染到纹理实例

时间:2021-09-12 18:36:03
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/glut.h>


GLuint v,f,f2,p;
float lpos[4] = {1,0.5,1,0};
GLint loc;
GLint uvloc;
GLint samp;
GLint sach;
GLuint textureId;
GLuint rboId;
GLuint fboId;
bool fboUsed;
float vertices[8] = {-2,2, 2,2, -2,-2, 2,-2};
float heights[4] = {2,2,-2,-2};
float uvm[8]={0,0,0,1,1,0,1,1};
char *textFileRead(char *fn) {


FILE *fp;
char *content = NULL;

int count=0;

if (fn != NULL) {
fp = fopen(fn,"rt");

if (fp != NULL) {

fseek(fp, 0, SEEK_END);
count = ftell(fp);
rewind(fp);

if (count > 0) {
content = (char *)malloc(sizeof(char) * (count+1));
count = fread(content,sizeof(char),count,fp);
content[count] = '\0';
}
fclose(fp);
}
}
return content;
}

int textFileWrite(char *fn, char *s) {

FILE *fp;
int status = 0;

if (fn != NULL) {
fp = fopen(fn,"w");

if (fp != NULL) {

if (fwrite(s,sizeof(char),strlen(s),fp) == strlen(s))
status = 1;
fclose(fp);
}
}
return(status);
}
void changeSize(int w, int h) {

// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;

float ratio = 1.0* w / h;

// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Set the correct perspective.
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0,5.0,0.0,
0.0,0.0,0.0,
1.0f,0.0f,0.0f);

}
float a = 0;

void renderScene(void) {
glBindTexture(GL_TEXTURE_2D, 0);
glViewport(0, 0, 512,512);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushAttrib(GL_VIEWPORT_BIT);


glLoadIdentity();
/*if(a<50)
glClearColor(0.02*a,1.0,0.0,1.0);*/
// glClearColor(1.0,0.0,1.0,1.0);
gluLookAt(0.0,5.0,0.0,
0.0,0.0,0.0,
1.0f,0.0f,0.0f);
//glutSolidTeapot(2.0);
//Lightfv(GL_LIGHT0, GL_POSITION, lpos);
glUniform1i(samp,0);
glUniform1f(sach,1.0f);
glRotatef(a,0,1,0);

glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glPopAttrib();

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT| GL_STENCIL_BUFFER_BIT);
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, 512,512);
glClearColor(0.0,0.0,1.0,1.0);
/*glBegin(GL_QUADS);

//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();

glColor3f(1, 1, 1);

glTexCoord2f(1, 1);
glVertex3d( 1, 1, 0);

glTexCoord2f(0, 1);
glVertex3d(-1, 1, 0);

glTexCoord2f(0, 0);
glVertex3d(-1, -1, 0);

glTexCoord2f(1, 0);
glVertex3d( 1, -1, 0);


glEnd();*/
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1i(samp,0);
glUniform1f(sach,0.0f);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);

a+=0.01;
glutSwapBuffers();

}

void processNormalKeys(unsigned char key, int x, int y) {

if (key == 27)
exit(0);
}

#define printOpenGLError() printOglError(__FILE__, __LINE__)

int printOglError(char *file, int line)
{
//
// Returns 1 if an OpenGL error occurred, 0 otherwise.
//
GLenum glErr;
int retCode = 0;

glErr = glGetError();
while (glErr != GL_NO_ERROR)
{
printf("glError in file %s @ line %d: %s\n", file, line, gluErrorString(glErr));
retCode = 1;
glErr = glGetError();
}
return retCode;
}


void printShaderInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;

glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
}
}

void printProgramInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;

glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
}
}


void setShaders() {

char *vs = NULL,*fs = NULL,*fs2 = NULL;

v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
f2 = glCreateShader(GL_FRAGMENT_SHADER);


vs = textFileRead("height.vert");
fs = textFileRead("height.frag");

const char * vv = vs;
const char * ff = fs;

glShaderSource(v, 1, &vv,NULL);
glShaderSource(f, 1, &ff,NULL);

free(vs);free(fs);

glCompileShader(v);
glCompileShader(f);

printShaderInfoLog(v);
printShaderInfoLog(f);
printShaderInfoLog(f2);

p = glCreateProgram();
glAttachShader(p,v);
glAttachShader(p,f);

glLinkProgram(p);
printProgramInfoLog(p);

glUseProgram(p);


loc = glGetAttribLocation(p,"height");

glEnableClientState(GL_VERTEX_ARRAY);
glEnableVertexAttribArray(loc);

uvloc = glGetAttribLocation(p,"uvco");

//glEnableClientState(GL_VERTEX_ARRAY);
glEnableVertexAttribArray(uvloc);
glVertexPointer(2,GL_FLOAT,0,vertices);

glVertexAttribPointer(loc,1,GL_FLOAT,0,0,heights);
glVertexAttribPointer(uvloc,2,GL_FLOAT,0,0,uvm);
samp=glGetUniformLocation(p,"picx");
sach=glGetUniformLocation(p,"sach");
/*
glVertexAttrib1f(loc,2.0);
glVertex2f(-1,1);

glVertexAttrib1f(loc,2.0);
glVertex2f(1,1);

glVertexAttrib1f(loc,-2.0);
glVertex2f(-1,-1);

glVertexAttrib1f(loc,-2.0);
glVertex2f(1,-1);
*/

}



void initf(){
/*GLubyte texas[128][128][4];
GLubyte blued=230;
for(int i=0;i<128;i++)
for(int j=0;j<128;j++){
texas[i][j][0]=blued-i;
texas[i][j][1]=0;
texas[i][j][2]=blued-j;
}*/



glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
//glBindTexture(GL_TEXTURE_2D, 0);
//glBindTexture(GL_TEXTURE_2D, textureId);
// create a renderbuffer object to store depth info
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
512,512);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

// create a framebuffer object

glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, textureId, 0);

// attach the renderbuffer to depth attachment point
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, rboId);

// check FBO status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
printf("byfgydzfgh");

// switch back to window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);

}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(512,512);
glutCreateWindow("MY FBO");

glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glutKeyboardFunc(processNormalKeys);

glEnable(GL_DEPTH_TEST);
//glClearColor(0.0,1.0,0.0,1.0);
//glEnable(GL_CULL_FACE);

glewInit();
if (glewIsSupported("GL_VERSION_2_0"))
printf("Ready for OpenGL 2.0\n");
else {
printf("OpenGL 2.0 not supported\n");
exit(1);
}
initf();
setShaders();
glutSetCursor(GLUT_CURSOR_DESTROY);
glutMainLoop();

return 0;
}

走了不少弯路终于做出来了,只是没明白为什么纹理会有一个向黑色的渐变,还可以再完善。

OpenGL FBO渲染到纹理实例