现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

windows下opengl(六):几种绘制方法的示例

2014-11-01 22:45 工业·编程 ⁄ 共 7110字 ⁄ 字号 暂无评论

    有前面5章的基础,接下来我们可以以自己的方式去实现一些经典书籍的示例程序。大多数的示例都存在过度封装的倾向,对于初学者来说,要找到“真正起作用的那行代码”非常困难。先把红宝书,即《opengl programming guide》第8版第3章关于各种绘制方式的例子用第五章封装的oglwindow库和glew库实现一下。

        具体的函数声明,参数说明通通省了,如果想了解,直接查红宝书吧,注意第8版电子书已经有了, OpenGL实在是变化很快的。

        下面直接上代码,程序说明:

        1)使用了oglwindow库、glew库

        2)在VS中创建win32应用程序(不是控制台项目)

        3)添加glew库和oglwindow头文件和库文件目录至VS环境

        4)链接库需要:opengl32.lib glew32.lib oglwindow.lib

//

//该示例演示:

//1 带平移矩阵的顶点着色器

//2 缩小矩阵写在顶点着色器里了

//3 演示了glDrawArrays等多种绘图方法

//

//

///////////////////////////////////////////////////////////////////////

//

// triangles.cpp

//

///////////////////////////////////////////////////////////////////////

#include <iostream>

using namespace std; 

#include <Windows.h>

#include <GL/glew.h>

#include <GL/wglew.h>

#include <oglWindow.h>

#pragma comment (lib, "opengl32.lib")

#pragma comment (lib , "oglwindow.lib")

#pragma comment (lib , "glew32.lib")

#define BUFFER_OFFSET(x)  ((const void*) (x))

enum Buffer_IDs { ArrayBuffer, NumBuffers }; 

enum Attrib_IDs { vPosition = 0,vColor }; 

GLuint ebo[1]; 

GLuint vao[1], vbo[1]; 

GLuint shaderprogram; 

GLuint CreateShader() 

//顶点着色器的源程序

    GLchar vertexshader[] ={ 

"#version 440\n"

"layout(location=0) in vec4 vPosition;\n"

"layout(location=1) in vec4 vColor;\n"

"out vec4 color;\n"

"uniform mat4 m;\n"

"void main()\n"

"{ mat4 m1 = mat4(0.2, 0.0,  0.0, 0.0,"

"                 0.0,  0.2, 0.0, 0.0,"

"                 0.0,  0.0,  0.2,0.0,"

"                 0.0,  0.0,  0.0, 1.0); "

"gl_Position = m * m1 * vPosition; "

"  color = vColor;\n }"

    }; 

//片段着色器的源程序

    GLchar fragshader[] ={ 

"#version 440\n"

"in  vec4 color;\n"

"out vec4  fColor;\n"

"void main()\n"

"{ fColor = color; }"

    }; 

//定义内部对象,使后续代码可以使用循环

struct Shader { 

        GLenum       type; 

        GLchar*      source; 

    }  shaders[2] = { 

        { GL_VERTEX_SHADER, vertexshader }, 

        { GL_FRAGMENT_SHADER, fragshader } 

    }; 

    GLuint program = glCreateProgram();//GPU创建程序对象

for ( int i = 0; i < 2; ++i ) { 

        Shader& s = shaders[i]; 

        GLuint shader = glCreateShader( s.type ); //GPU创建着色器对象

        glShaderSource( shader, 1, (const GLchar**) &s.source, NULL );//着色器绑定对应源程序

        glCompileShader( shader );//编译着色器

        GLint status; 

        glGetShaderiv(shader,GL_COMPILE_STATUS,&status); 

if(status == GL_FALSE) return 0; 

        glAttachShader( program, shader ); //将编译结果存入GPU程序

    } 

    glLinkProgram(program);               //将程序中的不同部分链接起来

    GLint status; 

    glGetProgramiv(program,GL_LINK_STATUS,&status); 

if(status == GL_FALSE) return 0; 

return program; 

//---------------------------------------------------------------------

//

// init

//

void init(void) 

//有4个顶点的顶点数组

const GLfloat vertex_positions[] = 

    { 

        -1.0f, -1.0f, 0.0f, 1.0f, 

        1.0f, -1.0f, 0.0f, 1.0f, 

        -1.0f, 1.0f, 0.0f, 1.0f, 

        1.0f, 1.0f, 0.0f, 1.0f, 

    }; 

//每个顶点对应的颜色数组

const GLfloat vertex_colors[] = 

    { 

        1.0f, 1.0f, 1.0f, 1.0f, 

        1.0f, 1.0f, 0.0f, 1.0f, 

        1.0f, 0.0f, 1.0f, 1.0f, 

        0.0f, 1.0f, 1.0f, 1.0f 

    }; 

//使用glDrawElements等绘图方式必须有的索引数组

static const GLushort vertex_indices[] = 

    { 

        0,1,2,3,0,1 

    }; 

//创建并绑定顶点数组对象

    glGenVertexArrays(1, vao); 

    glBindVertexArray(vao[0]); 

//创建、绑定并对顶点缓冲对象赋值

    glGenBuffers(1, vbo); 

    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); 

    glBufferData(GL_ARRAY_BUFFER,sizeof(vertex_positions) + sizeof(vertex_colors),NULL, GL_STATIC_DRAW); 

    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertex_positions), vertex_positions); 

    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertex_positions), sizeof(vertex_colors), vertex_colors); 

//创建、绑定并对索引数组对象赋值

    glEnableClientState(GL_ELEMENT_ARRAY_BUFFER); 

    glGenBuffers(1, ebo); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo[0]); 

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW); 

//编译、链接着色器

    GLuint program = CreateShader(); 

    shaderprogram = program; 

    glUseProgram(program); 

//设置着色器in类型变量指针

    glVertexAttribPointer(vPosition, 4, GL_FLOAT,GL_FALSE, 0, BUFFER_OFFSET(0)); 

    glEnableVertexAttribArray(vPosition); 

    glVertexAttribPointer(vColor, 4, GL_FLOAT,GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertex_positions))); 

    glEnableVertexAttribArray(vColor); 

//---------------------------------------------------------------------

//

// display

//

void display(void) 

//清屏

    glClear(GL_COLOR_BUFFER_BIT); 

//绑定顶点数组对象

    glBindVertexArray(vao[0]); 

// glDrawArrays方法

// 平移矩阵,沿x方向左移0.8

    GLfloat mat1[] = { 

        1.0f,  0.0f,  0.0f,  0.0f, 

        0.0f,  1.0f,  0.0f,  0.0f, 

        0.0f,  0.0f,  1.0f,  0.0f, 

        -0.8f, 0.0f,  0.0f,  1.0f 

    }; 

    GLint render_model_matrix_loc  = glGetUniformLocation( shaderprogram, "m" ); 

    glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, mat1); 

    glDrawArrays(GL_TRIANGLES, 0, 3); 

// glDrawElements

// 平移矩阵,沿x方向左移0.3

    GLfloat mat2[] = { 

        1.0f,  0.0f,  0.0f,  0.0f, 

        0.0f,  1.0f,  0.0f,  0.0f, 

        0.0f,  0.0f,  1.0f,  0.0f, 

        -0.3f, 0.0f,  0.0f,  1.0f 

    }; 

    glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, mat2); 

    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (GLvoid*)(0*sizeof(GLushort)));//最后一个参数是以字节为单位的偏移

// glDrawElementsBaseVertex

// 平移矩阵,沿x方向右移0.2

    GLfloat mat3[] = { 

        1.0f,  0.0f,  0.0f,  0.0f, 

        0.0f,  1.0f,  0.0f,  0.0f, 

        0.0f,  0.0f,  1.0f,  0.0f, 

        0.2f, 0.0f,  0.0f,  1.0f 

    }; 

    glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, mat3); 

    glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (GLvoid*)(0*sizeof(GLushort)),0); 

// glDrawArraysInstanced

// 平移矩阵,沿x方向左移0.7

    GLfloat mat4[] = { 

        1.0f,  0.0f,  0.0f,  0.0f, 

        0.0f,  1.0f,  0.0f,  0.0f, 

        0.0f,  0.0f,  1.0f,  0.0f, 

        0.7f, 0.0f,  0.0f,  1.0f 

    }; 

    glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, mat4); 

    glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1); 

    glFlush(); 

    SwapBuffers(wglGetCurrentDC()); 

///////////////////////////////////////////////////////////////////////////////

//窗口回调函数

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 

switch (uMsg)   

    {   

case WM_PAINT: 

        display(); 

break; 

case WM_SIZE: 

int width; 

int height; 

        height=lParam>>16; 

        width=lParam&0x0000FFFF; 

        glViewport(0,0,width,height); 

        UpdateWindow(hWnd); 

break; 

case WM_CLOSE:   

        DestroyWindow(hWnd);   

break;   

case WM_DESTROY:   

        PostQuitMessage(0);   

return 0;   

default:   

return DefWindowProc(hWnd,uMsg,wParam,lParam);   

    }   

return 0;   

////////////////////////////////////////////////////////////////////

// 入口函数

int _stdcall WinMain(HINSTANCE hInst,HINSTANCE hPreInstance,LPSTR lpCmdLine,int nShowCmd) 

//创建窗口

HWND hWnd = CreateDefaultOGLWindow(hInst,WndProc); 

//初始化顶点数据

    init(); 

//显示窗口

    ShowOGLWindow(hWnd); 

//进入主循环

    EnterMainLoop(); 

return 0; 

        运行结果

图6-1 红宝书示例修改

        对于着色器的一点说明:

//顶点着色器的源程序

GLchar vertexshader[] ={ 

"#version 440\n"

"layout(location=0) in vec4 vPosition;\n"

"layout(location=1) in vec4 vColor;\n"

"out vec4 color;\n"

"uniform mat4 m;\n"

"void main()\n"

"{ mat4 m1 = mat4(0.2, 0.0,  0.0, 0.0,"

"                 0.0,  0.2, 0.0, 0.0,"

"                 0.0,  0.0,  0.2,0.0,"

"                 0.0,  0.0,  0.0, 1.0); "

"gl_Position = m * m1 * vPosition; "

"  color = vColor;\n }"

}; 

//片段着色器的源程序

GLchar fragshader[] ={ 

"#version 440\n"

"in  vec4 color;\n"

"out vec4  fColor;\n"

"void main()\n"

"{ fColor = color; }"

}; 

        在顶点着色器中,m1是一个缩放矩阵,它把定义的三角形缩小到原大小的0.2倍,目的是为了能在一个窗口里放下4个三角形。

        m是平移矩阵,由应用程序写入着色器。

        片段着色器中的in修饰的变量color与顶点着色器中的out修饰变量color类型相同,名称也相同,glLinkProgram链接着色器程序时会把它们链接在一起,即顶点着色器输出的颜色值会作为片段着色器的颜色输入。
        这里只给出了主程序全部代码,需要oglwindow库可以在第5章最后找到链接,也可以通过3.3节中给出的代码自行组织。

给我留言

留言无头像?