创建一个三角形
#include <windows.h>
#include <stdio.h>
#include <GLEW/glew.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "winmm.lib")
struct Vertex
{
float pos[3];
float color[4];
};
LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDOWN:
break;
case WM_LBUTTONUP:
break;
case WM_MOUSEMOVE:
break;
case WM_RBUTTONDOWN:
break;
case WM_RBUTTONUP:
break;
case WM_KEYDOWN:
break;
case WM_KEYUP:
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
char *LoadFileContent(const char* path)
{
FILE *pFile = fopen(path, "rb");
if (pFile)
{
fseek(pFile, 0, SEEK_END);
int nLen = ftell(pFile);
char *buffer = new char[nLen + 1];
rewind(pFile);
fread(buffer, nLen, 1, pFile);
buffer[nLen] = '\0';
fclose(pFile);
return buffer;
}
fclose(pFile);
return nullptr;
}
//编译链接gpu程序
GLuint CreateGPUProgram(const char *vsShaderPath, const char *fsShaderPath)
{
GLuint vsShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fsShader = glCreateShader(GL_FRAGMENT_SHADER);
const char * vsCode = LoadFileContent(vsShaderPath);
const char * fsCode = LoadFileContent(fsShaderPath);
glShaderSource(vsShader, 1, &vsCode, nullptr);
glShaderSource(fsShader, 1, &fsCode, nullptr);
glCompileShader(vsShader);
glCompileShader(fsShader);
GLuint program = glCreateProgram();
glAttachShader(program, vsShader);
glAttachShader(program, fsShader);
glLinkProgram(program);
glDetachShader(program, vsShader);
glDetachShader(program, fsShader);
glDeleteShader(vsShader);
glDeleteShader(fsShader);
return program;
}
INT WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
//注册窗口
WNDCLASSEX wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = NULL;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = NULL;
wndclass.hIconSm = NULL;
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = GLWindowProc;
wndclass.lpszClassName = L"GLWindow";
wndclass.lpszMenuName = NULL;
wndclass.style = CS_VREDRAW | CS_HREDRAW;
ATOM atom = RegisterClassEx(&wndclass);
if (!atom) {
return -1;
}
RECT rect;
rect.left = 0;
rect.right = 1280;
rect.top = 0;
rect.bottom = 720;
AdjustWindowRect(&rect, WS_EX_OVERLAPPEDWINDOW, NULL);
//创建窗口
HWND hwnd = CreateWindowEx(NULL, L"GLWindow", L"OpenGL Window", WS_OVERLAPPEDWINDOW,
100, 100, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL);
GetClientRect(hwnd, &rect);
int viewportWidth = rect.right - rect.left;
int viewportHeight = rect.bottom - rect.top;
//创建OpenGL渲染窗口
//create opengl render context
HDC dc = GetDC(hwnd);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nVersion = 1;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
int pixelFormat = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, pixelFormat, &pfd);
HGLRC rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc); // setup OpenGL context complete
glewInit();
GLuint program = CreateGPUProgram("sample.vs", "sample.fs");
GLint posLocation, colorLocation, MLocation, VLocation, PLocation;
posLocation = glGetAttribLocation(program, "pos");
colorLocation = glGetAttribLocation(program, "color");
MLocation = glGetUniformLocation(program, "M");
VLocation = glGetUniformLocation(program, "V");
PLocation = glGetUniformLocation(program, "P");
Vertex vertex[3];
vertex[0].pos[0] = 0.f;
vertex[0].pos[1] = 0.f;
vertex[0].pos[2] = -100.f;
vertex[0].color[0] = 1.f;
vertex[0].color[1] = 1.f;
vertex[0].color[2] = 1.f;
vertex[0].color[3] = 1.f;
vertex[1].pos[0] = 10.f;
vertex[1].pos[1] = 0.f;
vertex[1].pos[2] = -100.f;
vertex[1].color[0] = 1.f;
vertex[1].color[1] = 1.f;
vertex[1].color[2] = 1.f;
vertex[1].color[3] = 1.f;
vertex[2].pos[0] = 0.f;
vertex[2].pos[1] = 10.f;
vertex[2].pos[2] = -100.f;
vertex[2].color[0] = 1.f;
vertex[2].color[1] = 1.f;
vertex[2].color[2] = 1.f;
vertex[2].color[3] = 1.f;
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex ) * 3, nullptr, GL_STATIC_DRAW);//内存数据到显卡
glBufferSubData(GL_ARRAY_BUFFER, sizeof(Vertex ) * 3, vertex);
glBindBuffer(GL_ARRAY_BUFFER, 0);
unsigned int indexes[] = { 0,1,2 };
GLuint ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3, indexes, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//显示窗口
glViewport(0, 0, viewportWidth, viewportHeight);
glClearColor(41.f / 255.f, 71.f / 255.f, 121.f / 255.f, 1.0f); //set "clear color" for background
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
float identity[] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
};
glm::mat4 projection = glm::perspective(45.f, 800.f / 600.f, 0.1f, 1000.f);
static float sTimeSinceStartUp = timeGetTime() / 1000.0f;
while (true)
{
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//draw scene
//计算两帧之间的时间
float currentTime = timeGetTime() / 1000.0f;
float timeElapse = currentTime - sTimeSinceStartUp;
sTimeSinceStartUp = currentTime;
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glUniformMatrix4fv(MLocation, 1, GL_FALSE, identity);
glUniformMatrix4fv(VLocation, 1, GL_FALSE, identity);
glUniformMatrix4fv(PLocation, 1, GL_FALSE, glm::value_ptr(projection));
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(posLocation);
glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 3));
//glDrawArrays(GL_TRIANGLES, 0, 3);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glUseProgram(0);
//printf("time elapse since last frame: %f\n", timeElapse);
//present scene
SwapBuffers(dc);
}
return 0;
}