Specular.vs
attribute vec3 pos;
attribute vec2 texcoord;
attribute vec3 normal;
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform mat4 NM;
varying vec3 V_Normal;
varying vec4 V_WorldPos;
void main()
{
V_Normal = mat3(NM) * normal;
V_WorldPos = M*vec4(pos,1.0);
gl_Position=P*V*M*vec4(pos,1.0);
}
Specular.fs
//uniform vec4 U_AmbientLightColor;
//uniform vec4 U_AmbientMaterial;
varying vec3 V_Normal;
varying vec4 V_WorldPos;
void main()
{
vec3 lightPos = vec3(10.0,10.0,0.0);
vec3 L = lightPos;
L = normalize(L);
vec3 n = normalize(V_Normal);
//ambient
vec4 AmbientLightColor = vec4(0.2,0.2,0.2,1.0);
vec4 AmbientMaterial = vec4(0.2,0.2,0.2,1.0);
vec4 ambientColor = AmbientLightColor * AmbientMaterial;
//diffuse
vec4 DiffuseLightColor = vec4(1.0,1.0,1.0,1.0);
vec4 DiffuseMaterial = vec4(0.4,0.4,0.4,1.0);
vec4 diffuseColor = DiffuseLightColor * DiffuseMaterial * max(0.0, dot(L,n));
//specular
vec3 reflectDir = normalize(reflect(-L,n));
vec4 SpecularLightColor = vec4(1.0,1.0,1.0,1.0);
vec4 SpecularMaterial = vec4(0.8,0.8,0.8,1.0);
//inverse view direction
vec3 viewDir = normalize(vec3(0.0) - V_WorldPos.xyz);
vec4 specularColor = SpecularLightColor * SpecularMaterial * pow(max(0.0, dot(viewDir, reflectDir)), 18.0);
gl_FragColor = ambientColor + diffuseColor + specularColor;
}
Main.cpp
#include <windows.h>
#include <stdio.h>
#include <GLEW/glew.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <glm/ext/matrix_transform.hpp>
#include "misc.h"
#include "model.h"
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "winmm.lib")
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);
}
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("res/shader/Specular.vs", "res/shader/Specular.fs");
GLint posLocation, texcoordLocation, normalLocation, MLocation, VLocation, PLocation, NMLocation;
posLocation = glGetAttribLocation(program, "pos");
texcoordLocation = glGetAttribLocation(program, "texcoord");
normalLocation = glGetAttribLocation(program, "normal");
MLocation = glGetUniformLocation(program, "M");
VLocation = glGetUniformLocation(program, "V");
PLocation = glGetUniformLocation(program, "P");
NMLocation = glGetUniformLocation(program, "NM");
//load obj model: vertexes, vertex count, indexes, index count
unsigned int *indexes = nullptr;
int vertexCount = 0, indexCount = 0;
VertexData*vertexes = LoadObjModel("res/model/Sphere.obj", &indexes, vertexCount, indexCount);
if (vertexes == nullptr)
{
printf("load obj model fail");
}
//obj model -> vbo & ibo
GLuint vbo = CreateBufferObject(GL_ARRAY_BUFFER, sizeof(VertexData) * vertexCount, GL_STATIC_DRAW, vertexes);
GLuint ibo = CreateBufferObject(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indexCount, GL_STATIC_DRAW, indexes);
printf("vetex count %d index count %d", vertexCount, indexCount);
glClearColor(0.f, 0.f, 0.f, 1.f);
//显示窗口
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
glEnable(GL_DEPTH_TEST);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
glm::mat4 identity = glm::mat4(1.0f);
glm::mat4 model;
model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -4.0f)); //平移
model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(0.f, 1.f, 0.f)); //旋转
//model = glm::scale(model, glm::vec3(0.01f, 0.01f, 0.01f)); //缩放
glm::mat4 projection = glm::perspective(45.f, (float)viewportWidth / (float)viewportHeight, 0.1f, 1000.f);
glm::mat4 normalMatrix = glm::inverseTranspose(model);
static float sTimeSinceStartUp = timeGetTime() / 1000.0f;
MSG msg;
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 | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glUniformMatrix4fv(MLocation, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(VLocation, 1, GL_FALSE, glm::value_ptr(identity));
glUniformMatrix4fv(PLocation, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(NMLocation, 1, GL_FALSE, glm::value_ptr(normalMatrix));
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(posLocation);
glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)0);
glEnableVertexAttribArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * 3));
glEnableVertexAttribArray(normalLocation);
glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * 5));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, indexCount, 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;
}
其他模块代码见上一章
计算机图形学 —— OpenGL绘制模型