我需要有一个图像作为我的代码(尺寸:3507x3281)的输出,由两个三角形(左上角和右下角)组成,每个三角形将在我的输出上给出一个不同的颜色/图像。
我读取了两个图像并用2个纹理(texture_1和texture_2)绑定它们。 之后我创建了与其各自图像相关的两个三角形。 我创建并绑定了Framebuffer对象并附加了纹理。最后,我将内容保存到图像文件(.ppm)。
问题:
我的结果(输出图像)是连贯的,几何上是正确的。但是,只有部分输出图像可见。它可见的部分有1366x768作为尺寸,这是我的屏幕分辨率。我在代码上遗漏了什么吗?
是否有与选项相关的内容" GL_DRAW_FRAMEBUFFER,GL_READ_FRAMEBUFFER和GL_FRAMEBUFFER"?只有" GL_DRAW_FRAMEBUFFER"给出连贯的结果。
我真的使用Framebuffer吗?因为,我读到,因为你使用FBO这种问题不会出现。
CODE:
#include <windows.h>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cstdio>
#include <string>
/// Definitions
#define checkImageWidth 500 /// for image - texture 1
#define checkImageHeight 500
#define width 2464 /// for image - texture 2
#define height 1648
static GLuint texture_1, texture_2;
static GLubyte checkImage[checkImageHeight][checkImageWidth][3];
GLuint fb = 1; ///Frame-buffer Object
/// Headers
GLuint raw_texture_load();
void FBO_2_PPM_file(int output_width, int output_height);
/// Functions
GLuint raw_texture_load()
{
/// image used for texture 1
unsigned char *data;
FILE *file;
// open texture data
file = fopen("C:\\Dataset\\image_1.raw", "rb");
if (file == NULL) return 0;
// allocate buffer
data = (unsigned char*) malloc(width * height * 3);
// read texture data
fread(data, width * height * 3, 1, file);
fclose(file);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
/// Texture 1
// allocate a texture name
glGenTextures(1, &texture_1);
// select our current texture
glBindTexture(GL_TEXTURE_2D, texture_1);
// select modulate to mix texture with color for shading
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// when texture area is large, bilinear filter the first mipmap
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// texture should tile
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// build our texture mipmaps
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
// free buffer
free(data);
/// image used for texture 2
FILE *image_4tx2;
if( (image_4tx2 = fopen("C:\\dataset\\image2.ppm","r")) == NULL )
{
printf("\n Problem with input for texture 2\n");
system("pause");
exit(1);
}
int i, j, max_ND, n_col, n_lin, Red, G, B;
char s1[20];
/// Read header
fscanf(image_4tx2,"%s",&s1);
fscanf(image_4tx2,"%s %s %s %s",&s1, &s1, &s1, &s1);
fscanf(image_4tx2,"%d %d",&n_col, &n_lin);
fscanf(image_4tx2,"%d",&max_ND);
for (i = 0; i < checkImageWidth; i++)
{
for (j = 0; j < checkImageHeight; j++)
{
fscanf(image_4tx2,"%d %d %d ",&Red, &G, &B);
checkImage[i][j][0] = (GLubyte) Red;
checkImage[i][j][1] = (GLubyte) G;
checkImage[i][j][2] = (GLubyte) B;
}
}
fclose(image_4tx2);
/// Texture 2
glGenTextures(2, &texture_2);
glBindTexture(GL_TEXTURE_2D, texture_2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, checkImageWidth, checkImageHeight,
0, GL_RGB, GL_UNSIGNED_BYTE, checkImage);
return texture_1;
}
void render()
{
GLdouble COORD_1[3], COORD_2[3], COORD_3[3], COORD[3];
/// Output image size
double col_siz_double = 3507.0;
double row_siz_double = 3281.0;
int col_siz_output_image = 3507;
int row_siz_output_image = 3281;
/// Aspect ratio
double ratio_col_row = col_siz_double/row_siz_double;
double aspect_E, aspect_N;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(ratio_col_row>=0.0)
{
aspect_E = 1.0;
aspect_N = 1.0/ratio_col_row;
glOrtho(0.0, 1.0*aspect_E, 0.0, 1.0*aspect_N, 0.0, 1.0);
}
else
{
aspect_E = 1.0/ratio_col_row;
aspect_N = 1.0;
glOrtho(0.0, 1.0*aspect_E, 0.0, 1.0*aspect_N, 0.0, 1.0);
}
gluLookAt( 0.0, 0.0, 1.0, /* eye */
0.0, 0.0, 0.0, /* center */
0, 1, 0); /* up */
/// Viewport
glViewport(0,0,col_siz_output_image,row_siz_output_image);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
/// Triangle 1 (upper-left half of the output)
glBindTexture(GL_TEXTURE_2D, texture_1);
glBegin(GL_TRIANGLES);
glTexCoord2d(0.0, 0.0);
COORD[0]= 0.0*aspect_E;
COORD[1]= 0.0*aspect_N;
COORD[2]= 1.0;
glVertex3d(COORD[0], COORD[1], COORD[2]);
glTexCoord2d(1.0, 1.0);
COORD[0]= 1.0*aspect_E;
COORD[1]= 1.0*aspect_N;
COORD[2]= 1.0;
glVertex3d(COORD[0], COORD[1], COORD[2]);
glTexCoord2d(0.0, 1.0);
COORD[0]= 0.0*aspect_E;
COORD[1]= 1.0*aspect_N;
COORD[2]= 1.0;
glVertex3d(COORD[0], COORD[1], COORD[2]);
glEnd();
/// Triangle 2 (low-right half of the output)
glBindTexture(GL_TEXTURE_2D, texture_2);
glBegin(GL_TRIANGLES);
glTexCoord2d(0.0, 0.0);
COORD[0]= 0.0*aspect_E;
COORD[1]= 0.0*aspect_N;
COORD[2]= 1.0;
glVertex3d(COORD[0], COORD[1], COORD[2]);
glTexCoord2d(1.0, 1.0);
COORD[0]= 1.0*aspect_E;
COORD[1]= 1.0*aspect_N;
COORD[2]= 1.0;
glVertex3d(COORD[0], COORD[1], COORD[2]);
glTexCoord2d(1.0, 0.0);
COORD[0]= 1.0*aspect_E;
COORD[1]= 0.0*aspect_N;
COORD[2]= 1.0;
glVertex3d(COORD[0], COORD[1], COORD[2]);
glEnd();
glFlush();
glDisable(GL_TEXTURE_2D);
static const GLenum draw_buffers[] =
{
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1
};
/// Generating and Biding the Framebuffer Object (FBO)
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
///Attaching both 2D texture to the FBO as color attachments
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, draw_buffers[0], GL_TEXTURE_2D, texture_2, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, draw_buffers[1], GL_TEXTURE_2D, texture_1, 0);
/// Specifying a list of color buffers to be drawn into
glDrawBuffers(2, draw_buffers);
/// Checking the FBO status
GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if( status != GL_FRAMEBUFFER_COMPLETE)
{
printf("\n\nFramebuffer status: %s\n\n",status);
system("pause");
}
/// Saving the results from the FBO (fb) to a PPM image file
FBO_2_PPM_file(col_siz_output_image,row_siz_output_image);
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
texture_1 = raw_texture_load();
render();
}
void FBO_2_PPM_file(int output_width, int output_height)
{
FILE *output_image;
/// READ THE PIXELS VALUES from FBO AND SAVE TO A .PPM FILE
int i, j, k;
unsigned char *pixels = (unsigned char*)malloc(output_width*output_height*4);
/// READ THE CONTENT FROM THE FBO
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glReadPixels(0, 0, output_width, output_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
output_image = fopen("C:\\Dataset\\output.ppm", "wt");
if(output_image == NULL)
{
printf("Problem @ output file!\n\n");
system("pause");
}
fprintf(output_image,"P3\n");
fprintf(output_image,"# Created by Ricao\n");
fprintf(output_image,"%d %d\n",output_width,output_height);
fprintf(output_image,"255\n");
k = 0;
for(i=output_height-1; i>-1; i--)
{
for(j=0; j<output_width; j++)
{
k = (i*output_width)+j;
/// saving only RGB
fprintf(output_image,"%u %u %u ",(unsigned int)pixels[4*k],(unsigned int)pixels[(4*k)+1],
(unsigned int)pixels[(4*k)+2]);
}
fprintf(output_image,"\n");
}
free(pixels);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(3507, 3281);
glutCreateWindow("Do not close this window!");
glutHideWindow();
/// Checking GLEW library
glewExperimental=TRUE;
GLenum err=glewInit();
if(err!=GLEW_OK)
{
printf("glewInit failed, aborting.");
printf("\tError: %s\n\n",glewGetErrorString(err));
system("pause");
}
if (GLEW_EXT_framebuffer_object != GL_TRUE)
{
printf("\n\n\t ** Error! GLEW_EXT_framebuffer_object != GL_TRUE \n\n");
system("pause");
}
/// To check the max size of the Framebuffer
int dims[2];
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &dims[0]);
///Executing the rendering process
init();
return 0;