我想使用opengl子窗口在一个窗口中显示两个不同的三角形。但它只显示后者。如果我调整创建子窗口的顺序,后一个将始终显示,第二个创建的子窗口将不会显示。
如果我评论第二个,第一个将显示。请帮助我,谢谢。
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
void mainDisplay();
void view1TriangleDisplay();
void view2TriangleDisplay();
// TODO: reshape
int initWindow(int argc, char *argv[])
{
glutInit(&argc, argv);
// TODO: glutInitContextVersion(3, 0);
glutInitDisplayMode(GLUT_RGBA | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH);
// glutInitWindowSize(640, 480);
glutInitWindowSize(512, 512);
GLuint window = glutCreateWindow("simple");
glutDisplayFunc(mainDisplay);
GLuint view1_triangle = glutCreateSubWindow(window, 0, 0, 256, 256);
glutDisplayFunc(view1TriangleDisplay);
GLuint view2_triangle = glutCreateSubWindow(window, 256, 0, 256, 256);
glutDisplayFunc(view2TriangleDisplay);
if (glewInit() != GLEW_OK){
return 1;
}
return 0;
}
GLuint view1_program = 0, view2_program = 0;
char *load_file(const char * path)
{
FILE *file_handler = fopen(path, "r");
if (file_handler == NULL){
return NULL;
}
if (fseek(file_handler, 0, SEEK_END) == -1){
return NULL;
}
long size = ftell(file_handler);
if (size == -1){
return NULL;
}
if (fseek(file_handler, 0, SEEK_SET) == -1){
return NULL;
}
char *content = (char *)malloc(size * sizeof(char) + 1);
if (content == NULL){
return NULL;
}
fread(content, 1, (size_t)size, file_handler);
if (ferror(file_handler)){
free(content);
fclose(file_handler);
return NULL;
}
fclose(file_handler);
content[size] = '\0';
// printf ("path : %s, size : %ld, content : %s\n", path, size, content);
return content;
}
void printLog(GLuint object)
{
char *logBuffer = NULL;
GLint logLength;
if (glIsShader(object)){
glGetShaderiv(object, GL_INFO_LOG_LENGTH, &logLength);
logBuffer = (char *)malloc(sizeof(char) * logLength);
glGetShaderInfoLog(object, logLength, NULL, logBuffer);
} else if (glIsProgram(object)){
glGetProgramiv(object, GL_INFO_LOG_LENGTH, &logLength);
logBuffer = (char *)malloc(sizeof(char) * logLength);
glGetProgramInfoLog(object, logLength, NULL, logBuffer);
} else {
return;
}
fprintf(stderr, "%s", logBuffer);
free(logBuffer);
}
GLint get_attrib(GLuint program, const char *attribute_name)
{
GLint attribute = glGetAttribLocation(program, attribute_name);
if (attribute == -1){
fprintf(stderr, "glGetAttribLocation attribute_name %s failed\n", attribute_name);
return -1;
}
return attribute;
}
GLint view1_attribute_coord2d, view2_attribute_coord2d;
GLuint create_shader(const char *path, GLenum type)
{
GLuint shader = glCreateShader(type);
char *shader_src = load_file(path);
if (shader_src == NULL){
return 0;
}
char *sources[2] = {
(char *)"#version 130\n",
shader_src
};
glShaderSource(shader, 2, (const char **)&sources, NULL);
free(shader_src);
glCompileShader(shader);
GLint status = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == 0){
fprintf(stderr, "compile shader failed\n");
printLog(shader);
return 0;
}
return shader;
}
GLuint create_program(const char *vertex_path, const char *fragment_path)
{
GLint status = GL_FALSE;
// create program
GLuint program = glCreateProgram();
GLuint shader = 0;
if (vertex_path != NULL){
// create vertex shader
if ((shader = create_shader(vertex_path, GL_VERTEX_SHADER)) == -1){
return -1;
}
glAttachShader(program, shader);
}
if (fragment_path != NULL){
// create fragment shader
if ((shader = create_shader(fragment_path, GL_FRAGMENT_SHADER)) == -1){
return -1;
}
glAttachShader(program, shader);
}
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == 0){
fprintf(stderr, "link shader failed");
printLog(program);
return -1;
}
return program;
}
int initResources()
{
view1_program = create_program("triangle.1.v.glsl", "triangle.1.f.glsl");
view1_attribute_coord2d = get_attrib(view1_program, "coord2d");
view2_program = create_program("triangle.2.v.glsl", "triangle.2.f.glsl");
view2_attribute_coord2d = get_attrib(view2_program, "coord2d");
return 0;
}
void freeResources()
{
// TODO: no need to free content?
if (view1_program != -1){
glDeleteProgram(view1_program);
}
if (view2_program != -1){
glDeleteProgram(view2_program);
}
// NOTE: let the os handle shader
// if (triangle_vertex_shader != 0){
// glDeleteShader(triangle_vertex_shader);
// }
// if (triangle_fragment_shader != 0){
// glDeleteShader(triangle_fragment_shader);
// }
}
void mainDisplay()
{
glClearColor(1.0, 1.0, 1.0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
}
void view1TriangleDisplay()
{
glClearColor(1.0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(view1_program);
glEnableVertexAttribArray(view1_attribute_coord2d);
// attach attribute
GLfloat triangle_vertices[6] = {
0.0, 0.8,
-0.8, -0.8,
0.8, -0.8
};
glVertexAttribPointer(view1_attribute_coord2d, 2, GL_FLOAT,
GL_FALSE, 0, triangle_vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(view1_attribute_coord2d);
glutSwapBuffers();
}
void view2TriangleDisplay()
{
glClearColor(0, 1.0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(view2_program);
glEnableVertexAttribArray(view2_attribute_coord2d);
// attach attribute
GLfloat triangle_vertices[6] = {
0.0, 0.8,
-0.8, -0.8,
0.8, -0.8
};
glVertexAttribPointer(view2_attribute_coord2d, 2, GL_FLOAT,
GL_FALSE, 0, triangle_vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(view2_attribute_coord2d);
glutSwapBuffers();
}
int main(int argc, char *argv[])
{
if (initWindow(argc, argv) != 0){
return 0;
}
if (initResources() == 0){
// glutDisplayFunc(onDisplay);
glutMainLoop();
}
freeResources();
return 0;
}
triangle.1.v.glsl
attribute vec2 coord2d;
void main()
{
gl_Position = vec4(coord2d, 0.0, 1.0);
}
triangle.1.f.glsl
void main()
{
gl_FragColor[0] = 0.0;
gl_FragColor[1] = 0.0;
gl_FragColor[2] = 1.0;
// gl_FragColor[3] = 0.4;
}
triangle.2.v.glsl
attribute vec2 coord2d;
void main()
{
gl_Position = vec4(coord2d, 0.0, 1.0);
}
triangle.2.f.glsl
void main()
{
gl_FragColor[0] = gl_FragCoord.x/256;
gl_FragColor[1] = gl_FragCoord.y/256;
gl_FragColor[2] = 0.5;
if (mod(gl_FragCoord.y, 30.0) > 15){
gl_FragColor[3] = 1;
} else {
gl_FragColor[3] = 0.4;
}
}