OpenGL FBO渲染到纹理实例

时间:2021-11-13 19:42:34
#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渲染到纹理实例