上一篇文章已经说明了如何使用texture, 但是颜色还不够真实,我们日常看到的颜色中有很多图片,能不能把这些图片真实的展示出来呢?答案是肯定的,比如一面墙,我们不需要专门去画这堵墙,可以把墙的图片贴上来就可以了。步骤是:
1 读取图片,区分RGBA
2 将图片当成texture去采样
3 draw并显示出来
图片有很多种格式 ,jpg, png, ppm, bmp等,可惜OpenGL并没有提供读取图片的API,这就需要我们自己去做了。常见的开源项目里面有很多可以完成这个操作的,比如SOIL,这里我们就看个简单的读取bmp格式的,以美女图片为例。
读取图片的函数为:
96 void read_bmp()
97 {
98 GLint pixel_length;
99
100 FILE* pfile = fopen("girl.bmp","rw+");
101 if(pfile == 0)
102 printf("File open failed\n");
103
104 fseek(pfile,0x0012,SEEK_SET);
105 fread(&image_width, sizeof(image_width), 1, pfile);
106 fread(&image_height, sizeof(image_height), 1, pfile);
107 printf("---image_width=%d\n", image_width);
108 printf("---image_height=%d\n", image_height);
109
110 pixel_length = image_width * 3;
111 printf("---pixellength=%d\n", pixel_length);
112 while(pixel_length % 4 != 0) pixel_length++;
113
114 pixel_length *= image_height;
115 printf("---pixellength=%d\n", pixel_length);
116
117 pixel_data = (GLubyte*)malloc(pixel_length);
118 if(pixel_data == 0) exit(0);
119
120 fseek(pfile, 54, SEEK_SET);
121 fread(pixel_data, pixel_length, 1, pfile);
122 for (int i = 0 ; i < 1000; i++)
123 {
124 if(pixel_data[i] != 0)
125 printf("---pixel_data=%d\n", pixel_data[i]);
126 }
127 fclose(pfile);
128 }
剩下的部分和上一篇文章差不多,不再赘述。整个程序如下:
1 #include
2 #include
3 #include
4 #include
5 #include
6 using namespace std;
7 #define BUFFER_OFFSET(x) ((const void*) (x))
8
9 enum VAO_IDs {Triangles, NumVAOs};
10 enum Buffer_IDs {ArrayBuffer, NumBuffers};
11 enum Attrib_IDs {vPosition = 0};
12
13 GLuint VAOs[NumVAOs];
14 GLuint Buffers[NumBuffers];
15 GLuint program;
16
17 GLushort indices[] = {
18 0, 1, 3, /* first triangle */
19 1, 2, 3 /* second triangle */
20 };
21
22 GLuint tex;
23
24 const GLchar* vertex_shader = "#version 300 es \n"
25 "layout(location=0) in vec3 vPosition;\n"
26 "layout(location=1) in vec2 texCo;\n"
27 "out vec2 TexC;\n"
28 "void main()\n"
29 "{\n"
30 "gl_Position = vec4(vPosition, 1.0);\n"
31 "TexC = vec2(texCo.x, texCo.y);\n"
32 "}\n";
33
34 const GLchar* fragment_shader = "#version 300 es \n"
35 "precision highp float; \n"
36 "uniform sampler2D color;\n"
37 "layout(location=0)out vec4 fColor;\n"
38 "in vec2 TexC;\n"
39 "void main()\n"
40 "{\n"
41 "fColor = texture2D(color, TexC);\n"
42 "}\n";
43
44 void init_shader()
45 {
46 // vertex shader
47 GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
48 glShaderSource(vertexShader, 1, &vertex_shader, NULL);
49 glCompileShader(vertexShader);
50 // check vertex shader compiling status
51 GLint compiled;
52 GLchar log[256];
53 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compiled);
54 if (!compiled)
55 {
56 glGetShaderInfoLog(vertexShader, 256, NULL, log);
57 std::cerr << "vertex shader compile failed" << log << std::endl;
58 }
59
60 // fragment shader
61 GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
62 glShaderSource(fragmentShader, 1, &fragment_shader, NULL);
63 glCompileShader(fragmentShader);
64 // check fragment shader compiling status
65 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compiled);
66 if (!compiled)
67 {
68 glGetShaderInfoLog(fragmentShader, 256, NULL, log);
69 std::cerr << "fragment shader compile failed" << log << std::endl;
70 }
71
72 // link shaders
73 program = glCreateProgram();
74 glAttachShader(program, vertexShader);
75 glAttachShader(program, fragmentShader);
76 glLinkProgram(program);
77
78 cout << "prog=" << program << endl;
79 //check link status
80 GLint linked;
81 glGetProgramiv(program, GL_LINK_STATUS, &linked);
82 if (!linked)
83 {
84 glGetProgramInfoLog(program, 256, NULL, log);
85 std::cerr << "shader linking failed" << log << std::endl;
86 }
87 // delete shader
88 glDeleteShader(vertexShader);
89 glDeleteShader(fragmentShader);
90 }
91
92 GLint image_width;
93 GLint image_height;
94 GLubyte* pixel_data;
95
96 void read_bmp()
97 {
98 GLint pixel_length;
99
100 FILE* pfile = fopen("girl.bmp","rw+");
101 if(pfile == 0)
102 cout << "File open failed" << endl;
103
104 fseek(pfile,0x0012,SEEK_SET);
105 fread(&image_width, sizeof(image_width), 1, pfile);
106 fread(&image_height, sizeof(image_height), 1, pfile);
107 cout << "---image_width=" << image_width << endl;
108 cout << "---image_height=" << image_height << endl;
109
110 pixel_length = image_width * 3;
111 cout << "---pixel_length=" << pixel_length << endl;
112 while(pixel_length % 4 != 0) pixel_length++;
113
114 pixel_length *= image_height;
115 cout << "---pixel_length=" << pixel_length << endl;
116
117 pixel_data = (GLubyte*)malloc(pixel_length);
118 if(pixel_data == 0) exit(0);
119
120 fseek(pfile, 54, SEEK_SET);
121 fread(pixel_data, pixel_length, 1, pfile);
122 for (int i = 0 ; i < 1000; i++)
123 {
124 if(pixel_data[i] != 0)
125 cout << "---pixel_data=" << (int)pixel_data[i] << endl;
126 }
127 fclose(pfile);
128 }
129
130 void init_data()
131 {
132 glClearColor(0, 0, 0, 0);
133 glClear(GL_COLOR_BUFFER_BIT);
134
135 read_bmp();
136
137 glGenVertexArrays(NumVAOs, VAOs);
138 glBindVertexArray(VAOs[Triangles]);
139
140 const GLfloat vertices[] = {
141 // positions
142 -1.0f, -1.0f, 0.0f, // top right
143 1.0f, -1.0f, 0.0f, // bottom right
144 1.0f, 1.0f, 0.0f, // bottom left
145 -1.0f, 1.0f, 0.0f, // top left
146
147 // texture coords
148 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f
149 };
150
151 glGenBuffers(NumBuffers, Buffers);
152 glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
153 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
154
155 GLuint ebo;
156 glGenBuffers(1, &ebo);
157 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
158 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
159
160 glGenTextures(1, &tex);
161 glBindTexture(GL_TEXTURE_2D, tex);
162
163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
165
166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
168 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image_width, image_height, 0, GL_BGR, GL_UNSIGNED_BYTE, pixel_data);
169
170 glUseProgram(program);
171
172 GLint texloc = glGetAttribLocation(program, "texCo");
173 cout << "texloc=" << texloc << endl;
174 GLint posloc = glGetAttribLocation(program, "vPosition");
175 cout << "posloc=" << posloc << endl;
176
177 glEnableVertexAttribArray(posloc);
178 glVertexAttribPointer(posloc, 3, GL_FLOAT, GL_FALSE, 0, 0);
179
180 glEnableVertexAttribArray(texloc);
181 glVertexAttribPointer(texloc, 2, GL_FLOAT, GL_FALSE, 0, (void*)(12*sizeof(float)));
182 }
183
184 void display()
185 {
186 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
187 glFlush();
188 }
189
190 int main(int argc, char* argv[])
191 {
192 glutInit(&argc, argv);
193 glutInitDisplayMode(GLUT_RGBA);
194 glutInitWindowSize(300 ,300);
195 glutInitWindowPosition(100, 100);
196 glutCreateWindow("Learn opengl: load texture");
197
198 const char* version = (const char*)glGetString(GL_VERSION);
199 cout << "version=" << version << endl;
200 const char* vendor = (const char*)glGetString(GL_VENDOR);
201 cout << "vendor=" << vendor << endl;
202
203 const char* render = (const char*)glGetString(GL_RENDERER);
204 cout << "render=" << render << endl;
205
206 glewExperimental = GL_TRUE;
207 if(glewInit())
208 {
209 std::cout << "Unable to Initialize" << std::endl;
210 exit(1);
211 }
212 init_shader();
213 init_data();
214 glutDisplayFunc(display);
215 glutMainLoop();
216 }
运行完后,就可以显示出来图片了: