openGL学习(一)

openGL(一)

由于近期需要参加个比赛,需要一个demo,主题框架使用openGL来搭,刚好来学习下openGL,参考的工程为来自CMU,但是其使用的openGL都是老古董了,准备使用最近的翻修下。
PS:openGL现在都更新到4.5了,而且不能向下兼容。因此根据oprnGL3.3 tutorail 来进行学习。没有使用其中的窗口库(GLFW),使用FLTK的窗口建立(自我感觉更好用)。

首先是显示窗口的搭建

主要思想就是先封装窗口,包括菜单、显示窗口等,然后是界面操作,包括按键、鼠标等操作,最后就是建立简单的世界。

  • 主界面
  • 菜单
  • 键盘、鼠标操作
  • 世界设置(世界坐标系,地面等)

主界面

就是显示一个窗口界面,十分简单

Fl_Window *form = NULL; // Global form 
form = make_window();
form->show();

就是定义一个窗口,建造一个窗口,然后显示。其中,make_window函数构造为:

Fl_Window * make_window()
{
    Fl_Window * w;
    //main window
    {
        Fl_Window * o = main_window = new Fl_Window(741, 622, "Motion Player");
        w = o;
        //add other components
        {

        }
        o->end();
    }

    return w;
}

结果如下:
窗口界面

菜单

接着就是往窗口内添加菜单按钮了。
就是在make_window() 函数中添加其他组件:
部分代码如下:

        //单选按钮
        {
            Fl_Light_Button * o = record_button = new Fl_Light_Button(380, 575, 40, 25, "R");
            o->callback((Fl_Callback *)record_callback, (void*)(0));
        }
        //开始按钮
        {
            Fl_Button * o = play_button = new Fl_Button(500, 575, 35, 25, "@>");
            o->labeltype(FL_SYMBOL_LABEL);
            o->labelsize(12);
            o->callback((Fl_Callback *)play_callback, (void*)(0));
        }

注意:由于绘制块需要连续绘制画面,需要定义绘制函数,因此我们定义一个类来继承Fl_Gl_Window类(一个与openGL绘制的类)。需要重写绘制和窗口调用函数:

class Draw_Gl_Window : public Fl_Gl_Window
{
public:
    //使用父类构造器
    inline Draw_Gl_Window(int x, int y, int w, int h, const char *l = 0) :
        Fl_Gl_Window(x, y, w, h, l){};

    /*重载父类函数*/
    //绘制函数
    void draw();
    //窗口调用函数,当空间发生事件时被Anim_Gl_Window调用,一般为键盘和鼠标事件
    int handle(int event);
}

最后结果如下:
菜单

键盘鼠标操作

键盘和鼠标操作需要在继承Fl_Gl_Window类中的handle() 方法操作,用于获取和处理键盘、鼠标操作。其代码如下:

int Draw_Gl_Window::handle(int event)
{
    int handled = 1;
    //鼠标键盘事件(左键移动 右键选择 滚轴缩放)
    switch (event)
    {
        //鼠标滚轴
    case FL_MOUSEWHEEL:
        break;

    //鼠标释放(包括左右键) 
    case FL_RELEASE:
        break;

        //鼠标按下(包括左右键)button表示按的键 左键1 中间2 右键3
    case FL_PUSH:
        break;

    //鼠标按下移动(包括左右键)
    case FL_DRAG:
        break;

    default:
        // 其他事件使用父类
        break;
    }
    return handled;
}

世界坐标系

openGL绘制
首先需要绘制一个平面作为地面。
主要就是对GLEW的初始化,然后就是绘制。

初始化

// Initialize GLEW
if (glewInit() != GLEW_OK) {
    fprintf(stderr, "Failed to initialize GLEW\n");
    getchar();
    exit(-1);
}
// Dark blue background
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
initGround(); // 初始化陆地

对GLEW首先初始化,然后初始化地面,代码主要如下:

//定义形状
static const GLfloat g_vertex_buffer_data[] = {
    -0.8f, -0.8f, 0.0f,
    ...
};

//定义颜色
static const GLfloat g_color_buffer_data[] = {
    1.0f, 0.0f, 0.0f,
    ...
};
// 定义第一个缓冲 加载形状 
glGenBuffers(1, &vertexbuffer);  //创建
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); //绑定
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);  //填充
glEnableVertexAttribArray(0); //设置定点属性
//定义第二个缓冲 加载颜色
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,0, (void*)0);

//加载着色器
bool sv = shVertex.LoadShader("shader.vert", GL_VERTEX_SHADER);
bool sf = shFragment.LoadShader("shader.frag", GL_FRAGMENT_SHADER);
if (!sv || !sf)
{
    printf("No File of shader!\n");
    exit(-1);
}
//创建着色器
spMain.CreateProgram();
spMain.AddShaderToProgram(&shVertex);
spMain.AddShaderToProgram(&shFragment);

spMain.LinkProgram();
spMain.UseProgram();

openGL把图形位置和颜色都读入到缓冲中,然后使用着色器把颜色赋给图形。
最后只需要在绘制的回调函数中绘制图像:

//绘制陆地
void Draw_Gl_Window::drawGround(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 
}

其中glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 根据不同的形状进行调整参数。

总结:
openGL中文学习这个是之前那文章的中文翻译,自我感觉讲的有些讲的不是很清楚,比如Shader(着色器),建议结合OpenGL 3.3 - Tutorials 一起看,最主要把Shader搞懂,这个是openGL重点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值