在我的台式电脑(Linux,OpenSuse 42.2,GraKa:Nvidia GTX 960)上,下面的程序运行正常。它打开一个窗口,其中三个轴X,Y,Z为红色,绿色,蓝色,您可以使用箭头按钮围绕轴移动相机。
在我的Linux笔记本电脑上(OpenSuse 42.3,Intel 5500上的Mesa DRI),该程序只显示黑屏但没有轴。 “glxgears”在笔记本电脑上运行良好,因此原则上OpenGL必须正常工作。
根据我的理解,我必须编写一些不是以便携方式编写的东西,某处依赖于我不应该拥有的东西。
我已经重新阅读了几个SDL2教程,但是我没有看到我遗漏或做错了什么。
如何查看我的程序是否可以移植,或者更好的我如何找到非便携式部件?
Compilerflags:
`sdl2-config --cflags` -I. -Isrc -g
Linkerflags:
`sdl2-config --libs` -lGLEW -lGL -lpthread -lm
main.c中:
#include <GL/glew.h>
#include <GL/glu.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include "gl_common.h"
int width, height;
SDL_Surface* screen;
SDL_Surface* image;
int stop;
SDL_Window* window = NULL;
SDL_GLContext context;
int joy;
float wx, wy;
float ra;
float dx = 0.05;
float dy = 0.05;
float dr = 0.005;
Uint32 last_time;
static float c = M_PI / 180.0;
GLfloat cam_x, cam_y, cam_z;
GLuint program_object;
int is_initialised = 0;
GLfloat u_mvp[16];
GLint u_mvp_loc;
#define AL 1.4
#define AX 0.15
#define AY 0.05
GLfloat axis[] = {
// x, red
0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
AL, 0.0, 0.0, 1.0, 0.0, 0.0,
AL - AX, AY, 0.0, 1.0, 0.0, 0.0,
AL - AX, -AY, 0.0, 1.0, 0.0, 0.0,
AL, 0.0, 0.0, 1.0, 0.0, 0.0,
AL - AX, 0.0, AY, 1.0, 0.0, 0.0,
AL - AX, 0.0, -AY, 1.0, 0.0, 0.0,
AL, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
// y, green
0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
0.0, AL, 0.0, 0.0, 1.0, 0.0,
0.0, AL-AX, AY, 0.0, 1.0, 0.0,
0.0, AL-AX, -AY, 0.0, 1.0, 0.0,
0.0, AL, 0.0, 0.0, 1.0, 0.0,
AY, AL-AX, 0.0, 0.0, 1.0, 0.0,
-AY, AL-AX, 0.0, 0.0, 1.0, 0.0,
0.0, AL, 0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
// z, blue
0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
0.0, 0.0, AL, 0.0, 0.0, 1.0,
AY, 0.0, AL-AX, 0.0, 0.0, 1.0,
-AY, 0.0, AL-AX, 0.0, 0.0, 1.0,
0.0, 0.0, AL, 0.0, 0.0, 1.0,
0.0, AY, AL-AX, 0.0, 0.0, 1.0,
0.0, -AY, AL-AX, 0.0, 0.0, 1.0,
0.0, 0.0, AL, 0.0, 0.0, 1.0,
0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
};
#define AXIS_SIZE (sizeof(axis) / 6 / sizeof(GLfloat))
void quit(void) {
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
}
void draw() {
GLfloat proj_mat[16];
GLfloat model_mat[16];
GLfloat model_mat2[16];
GLfloat ctr[3];
GLfloat eye[3];
GLfloat up[3];
glViewport(0, 0, width, height);
mat_glu_perspective(proj_mat, 45.0f, (GLfloat)(width) / height, 0.1f, 100.0f);
#if 0
printf("\n\nproj_mat\n");
mat_show(u_mvp);
#endif
eye[0] = cam_x;
eye[1] = cam_y;
eye[2] = cam_z;
ctr[0] = 0.0;
ctr[1] = 0.0;
ctr[2] = 0.0;
up[0] = 0.0;
up[1] = 0.0;
up[2] = 1.0;
mat_glu_look_at(model_mat, eye, ctr, up);
mat_mul(u_mvp, proj_mat, model_mat);
#if 0
printf("\n\nu_mvp\n");
mat_show(u_mvp);
#endif
glUniformMatrix4fv(u_mvp_loc, 1, GL_FALSE, u_mvp);
glClearColor ( 0.0, 0.0, 0.0, 1.0 );
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
// glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// glCullFace(GL_FRONT_AND_BACK);
glUseProgram(program_object);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 6 * sizeof(GLfloat), axis);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 6 * sizeof(GLfloat), axis+3);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
// glDisableVertexAttribArray(2);
// glDisableVertexAttribArray(3);
glDrawArrays(GL_LINE_STRIP, 0, AXIS_SIZE);
SDL_GL_SwapWindow(window);
}
void init_gl(void) {
const char* vsh;
const char* fsh;
GLuint vertex_shader;
GLuint fragment_shader;
GLint linked;
vsh = load_file("shader.vsh");
fsh = load_file("shader.fsh");
fprintf(stderr, "vertex shader\n");
vertex_shader = load_shader(GL_VERTEX_SHADER, vsh);
fprintf(stderr, "fragment shader\n");
fragment_shader = load_shader(GL_FRAGMENT_SHADER, fsh);
program_object = glCreateProgram();
if(program_object == 0) {
printf("program object is 0\n");
exit(-10);
}
glAttachShader(program_object, vertex_shader);
glAttachShader(program_object, fragment_shader);
glBindAttribLocation(program_object, 0, "a_pos");
glBindAttribLocation(program_object, 1, "a_col");
glLinkProgram(program_object);
glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
if(!linked) {
GLint info_len;
glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1) {
char* info_log = (char*)malloc(info_len);
glGetProgramInfoLog(program_object, info_len, NULL, info_log);
fprintf(stderr, "<%s>\n\n", info_log);
free(info_log);
exit(-1);
}
glDeleteProgram(program_object);
exit(-11);
}
mat_identity(u_mvp);
u_mvp_loc = glGetUniformLocation(program_object, "u_mvp");
}
void update_cam(void) {
cam_x = ra*cos(c*wx)*cos(c*wy);
cam_y = ra*sin(c*wx)*cos(c*wy);
cam_z = ra*sin(c*wy);
}
void left(Uint32 d) {
wx -= dx*d;
if(wx < 0.0) wx += 360.0;
update_cam();
}
void right(Uint32 d) {
wx += dx*d;
if(wx > 360.0) wx -= 360.0;
update_cam();
}
void up(Uint32 d) {
if(wy + dy*d < 90.0) {
wy += dy*d;
update_cam();
}
}
void down(Uint32 d) {
if(wy - dy*d > -90.0) {
wy -= dy*d;
update_cam();
}
}
void zoom_in(Uint32 d) {
if(ra > 1.0) ra -= dr*d;
update_cam();
}
void zoom_out(Uint32 d) {
if(ra < 30.0) ra += dr*d;
update_cam();
}
static Uint32 time_diff(void) {
Uint32 ret;
Uint32 now = SDL_GetTicks();
ret = now - last_time;
last_time = now;
return ret;
}
int main(int argc, char** argv) {
SDL_Event event;
int k;
Uint32 d;
atexit(quit);
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("couldn't init: %s\n", SDL_GetError());
exit(-1);
}
width = 1024;
height = 768;
//Use OpenGL 3.2 core
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1);
window = SDL_CreateWindow( "SDL OpenGL exaple", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL );
if( window == NULL ) {
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
exit(-2);
}
context = SDL_GL_CreateContext( window );
if( context == NULL ) {
printf( "OpenGL context could not be created! SDL Error: %s\n", SDL_GetError() );
exit(-3);
}
glewExperimental = GL_TRUE;
GLenum glewError = glewInit();
if( glewError != GLEW_OK ) {
printf( "Error initializing GLEW! %s\n", glewGetErrorString( glewError ) );
exit(-4);
}
screen = SDL_GetWindowSurface( window );
init_gl();
is_initialised = 1;
wx = 150.0;
wy = 0.0;
ra = 4.0;
update_cam();
d = time_diff();
joy = 0;
stop = 0;
while(!stop) {
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
do_exit:
exit(-1);
stop = 1;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_ESCAPE:
case 'q':
goto do_exit;
break;
case SDLK_LEFT:
joy |= 4;
break;
case SDLK_RIGHT:
joy |= 8;
break;
case SDLK_UP:
joy |= 1;
break;
case SDLK_DOWN:
joy |= 2;
break;
case SDLK_PAGEUP:
joy |= 16;
break;
case SDLK_PAGEDOWN:
joy |= 32;
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym) {
case SDLK_LEFT:
joy &= ~4;
break;
case SDLK_RIGHT:
joy &= ~8;
break;
case SDLK_UP:
joy &= ~1;
break;
case SDLK_DOWN:
joy &= ~2;
break;
case SDLK_PAGEUP:
joy &= ~16;
break;
case SDLK_PAGEDOWN:
joy &= ~32;
break;
}
break;
}
}
d = time_diff();
if(joy & 1) up(d);
if(joy & 2) down(d);
if(joy & 4) left(d);
if(joy & 8) right(d);
if(joy & 16) zoom_in(d);
if(joy & 32) zoom_out(d);
draw();
}
return 0;
}
gl_common.c:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "gl_common.h"
// Matrizen werden spaltenweise angegeben
#define IX(x, y) ((y) + ((x) * 4))
void mat_show(GLfloat m[]) {
int x, y, i;
for(y = 0; y < 4; y++) {
for(x = 0; x < 4; x++) {
i = IX(x, y);
printf("%8.5f ", m[i]);
}
printf("\n");
}
}
GLfloat vec_len(GLfloat x[]) {
return sqrt((x[0]) * (x[0]) + (x[1]) * (x[1]) + (x[2]) * (x[2]));
}
void vec_norm(GLfloat x[]) {
GLfloat l = vec_len(x);
x[0] /= l;
x[1] /= l;
x[2] /= l;
}
void vec_copy(GLfloat dest[], const GLfloat src[]) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
}
void vec_diff(GLfloat res[], const GLfloat a[], const GLfloat b[]) {
res[0] = a[0] - b[0];
res[1] = a[1] - b[1];
res[2] = a[2] - b[2];
}
void vec_cross_product(GLfloat res[], const GLfloat a[], const GLfloat b[]) {
res[0] = a[1]*b[2] - b[1]*a[2];
res[1] = a[2]*b[0] - b[2]*a[0];
res[2] = a[0]*b[1] - b[0]*a[1];
}
GLfloat vec_scalar_product(const GLfloat a[], const GLfloat b[]) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
}
void mat_identity(GLfloat res[]) {
res[0] = 1.0f;
res[1] = 0.0f;
res[2] = 0.0f;
res[3] = 0.0f;
res[4] = 0.0f;
res[5] = 1.0f;
res[6] = 0.0f;
res[7] = 0.0f;
res[8] = 0.0f;
res[9] = 0.0f;
res[10] = 1.0f;
res[11] = 0.0f;
res[12] = 0.0f;
res[13] = 0.0f;
res[14] = 0.0f;
res[15] = 1.0f;
}
void mat_mul(GLfloat res[], const GLfloat a[], const GLfloat b[]) {
GLfloat tmp;
int x, y, i;
for(y = 0; y < 4; y++) {
for(x = 0; x < 4; x++) {
tmp = 0.0f;
for(i = 0; i < 4; i++) {
tmp += a[IX(i, y)] * b[IX(x, i)];
}
res[IX(x, y)] = tmp;
}
}
}
void mat_glu_look_at(GLfloat res[],
const GLfloat eye[],
const GLfloat center[],
const GLfloat up[])
{
GLfloat f[3]; // forward
GLfloat upc[3]; // up copy
GLfloat s[3]; // side
GLfloat u[3]; // up
GLfloat tmp[16];
GLfloat trl[16];
vec_diff(f, center, eye);
vec_norm(f);
vec_copy(upc, up);
vec_cross_product(s, f, upc);
vec_cross_product(u, s, f);
vec_norm(s);
vec_norm(u);
tmp[0] = s[0];
tmp[1] = u[0];
tmp[2] = -f[0];
tmp[3] = 0.0f;
tmp[4] = s[1];
tmp[5] = u[1];
tmp[6] = -f[1];
tmp[7] = 0.0f;
tmp[8] = s[2];
tmp[9] = u[2];
tmp[10] = -f[2];
tmp[11] = 0.0f;
tmp[12] = 0.0f;
tmp[13] = 0.0f;
tmp[14] = 0.0f;
tmp[15] = 1.0f;
mat_identity(trl);
trl[12] = -eye[0];
trl[13] = -eye[1];
trl[14] = -eye[2];
mat_mul(res, tmp, trl);
}
void mat_glu_perspective(GLfloat res[], GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) {
GLfloat sine, cotangent, deltaZ;
GLfloat radians = fovy / 2 * 3.1415926536 / 180;
deltaZ = zFar - zNear;
sine = sin(radians);
if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
return;
}
cotangent = cos(radians) / sine;
res[0] = cotangent / aspect;
res[1] = 0.0;
res[2] = 0.0;
res[3] = 0.0;
res[4] = 0.0;
res[5] = cotangent;
res[6] = 0.0;
res[7] = 0.0;
res[8] = 0.0;
res[9] = 0.0;
res[10] = -(zFar + zNear) / deltaZ;
res[11] = -1.0;
res[12] = 0.0;
res[13] = 0.0;
res[14] = -2 * zNear * zFar / deltaZ;
res[15] = 0.0;
}
///////////
GLuint load_shader(GLenum type, const char* src) {
GLuint shader;
GLint compiled;
shader = glCreateShader(type);
if(shader == 0) return 0;
glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled) {
GLint info_len;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1) {
char* info_log = (char*)malloc(info_len);
glGetShaderInfoLog(shader, info_len, NULL, info_log);
fprintf(stderr, "<<<\n%s\n>\n\n", info_log);
free(info_log);
}
glDeleteShader(shader);
exit(-1);
return 0;
}
return shader;
}
const char* load_file(const char* fname) {
FILE* fd;
const char* ret;
size_t len;
fd = fopen(fname, "rb");
if(fd == NULL) {
fprintf(stderr, "could not load <%s>\n", fname);
return NULL;
}
fseek(fd, -1, SEEK_END);
len = ftell(fd);
rewind(fd);
ret = (const char*)malloc(len + 1);
if(ret == NULL) {
fclose(fd);
fprintf(stderr, "could not get memory <%i>\n", len);
fclose(fd);
return NULL;
}
fread((void*)ret, 1, len, fd);
((char*)ret)[len] = 0;
// fprintf(stdout, "<%s>\n\n", ret);
return ret;
}
gl_common.h:
#ifndef GL_COMMON_H
#define GL_COMMON_H 1
#include <GL/glew.h>
#include <GL/gl.h>
#include <stdio.h>
#define QWE fprintf(stderr, "%s, %i\n", __FILE__, __LINE__)
typedef struct {
GLuint program_object;
int width;
int height;
GLfloat cam_x;
GLfloat cam_y;
GLfloat cam_z;
} UserData;
extern GLuint texbase[];
extern GLuint load_shader(GLenum type, const char* src);
extern const char* load_file(const char* fname);
/* math stuff */
extern GLfloat vec_len(GLfloat x[]);
extern void vec_norm(GLfloat x[]);
extern void vec_copy(GLfloat dest[], const GLfloat src[]);
extern void vec_diff(GLfloat res[], const GLfloat a[], const GLfloat b[]);
extern void vec_cross_product(GLfloat res[], const GLfloat a[], const GLfloat b[]);
extern GLfloat vec_scalar_product(const GLfloat a[], const GLfloat b[]);
extern void mat_mul(GLfloat res[], const GLfloat a[], const GLfloat b[]);
extern void mat_identity(GLfloat res[]);
extern void mat_glu_look_at(GLfloat res[],
const GLfloat eye[],
const GLfloat center[],
const GLfloat up[]);
extern void mat_glu_perspective(GLfloat res[], GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
extern void mat_show(GLfloat m[]);
#endif
shader.fsh:
#version 130
precision mediump float;
varying vec4 v_col;
void main()
{
gl_FragColor = v_col;
}
shader.vsh:
#version 130
uniform mat4 u_mvp;
attribute vec4 a_pos;
attribute vec4 a_col;
varying vec4 v_col;
const float c_zero = 0.0;
const float c_one = 1.0;
void main()
{
gl_Position = u_mvp * a_pos;
v_col = a_col;
}