OpenGL超级宝典(第7版)笔记14 前三章实例 下个五子棋全代码 (附)
程序员文章站
2022-03-05 09:42:41
...
OpenGL超级宝典(第7版)笔记14 前三章实例 下个五子棋全代码 (附)
#pragma once
#ifndef BASIC_RA
#define BASIC_RA
#include<iostream>
#include<Windows.h>
#define GLEW_STATIC
#include<glew.h>
#include<glfw3.h>
#include<math.h>
#endif //!BASIC_RA
void startup();
void render(double currentTime);
void shutdown();
void compile_shader(void);
void delete_shader(void);
GLuint linkprogram1(void);
GLuint linkprogram2(void);
GLuint vs[3]={0};
GLuint tcs[3]={0};
GLuint tes[3]={0};
GLuint gs[3]={0};
GLuint fs[3]={0};
GLuint rendering_program1;
GLuint rendering_program2;
GLuint vertex_array_object;
int windowhigh = 1000;
int windowwide = 1000;
GLdouble lastx = 0.0f;
GLdouble lasty = 0.0f;
GLdouble kickx = 0.0f;
GLdouble kicky = 0.0f;
GLint arrayx = 0;
GLint arrayy = 0;
GLint nowkind = 1;//黑为1白为2
int iswin = 0;
GLint judgewin(GLint x, GLint y);
struct chess{
GLchar chesskind=0;
//还可以给棋子添加更多的属性~
};
chess chessboard[17][17];
GLint chess_number=0;
GLchar chess_draw_list[17*17][3]={0};
//void drawString(const char* str) //屏幕显示字体
//{
// static int isFirstCall = 1;
// static GLuint lists;
//
// if (isFirstCall) {
// isFirstCall = 0;
// // 申请MAX_CHAR个连续的显示列表编号
// lists = glGenLists(200);
// // 把每个字符的绘制命令都装到对应的显示列表中
// wglUseFontBitmaps(wglGetCurrentDC(), 0, 20, lists);
// }
// // 调用每个字符对应的显示列表,绘制每个字符
// for (; *str != '\0'; ++str) {
// glCallList(lists + *str);
// }
//}
//void selectFont(int size, int charset, const char* face) {
// HFONT hFont = CreateFontA(size, 0, 0, 0, FW_MEDIUM, 0, 0, 0,
// charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
// DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, face);
// HFONT hOldFont = (HFONT)SelectObject(wglGetCurrentDC(), hFont);
// DeleteObject(hOldFont);
//}
我想试着在屏幕上输出字,但是没有成功~~~
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
// if (lastx == 0.0f) {
// lastx = xpos;
// }
// if (lasty == 0.0f) {
// lasty = ypos;
// }
// if((angy+ypos-lasty)*rotasen>3.141f/2.0f){
// angy=3.141f/(rotasen*2.0f);
// }else if((angy+ypos-lasty)*rotasen<-3.141f/2.0f){
// angy=-3.141f/(rotasen*2.0f);
// }else{
// angy+=ypos-lasty;
// }
// angx+=xpos-lastx;
lastx=xpos;
lasty=ypos;
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
int whichkey=0;//左键为1右键为2中键为3
if (action == GLFW_PRESS) switch (button)
{
case GLFW_MOUSE_BUTTON_LEFT:
kickx = lastx;
kicky = lasty;
whichkey=1;
std::cout << "left down" << std::endl;
std::cout << lastx << " " << lasty << std::endl;
break;
case GLFW_MOUSE_BUTTON_MIDDLE:
kickx = lastx;
kicky = lasty;
whichkey=3;
std::cout << "mid down" << std::endl;
std::cout << lastx << " " << lasty << std::endl;
break;
case GLFW_MOUSE_BUTTON_RIGHT:
kickx = lastx;
kicky = lasty;
whichkey=2;
std::cout << "right down" << std::endl;
std::cout << lastx << " " << lasty << std::endl;
if (nowkind == 1)
nowkind = 2;
else
nowkind = 1;
break;
default:
return;
}
switch(whichkey){
case 1:
if (kickx > 150 && kicky > 150 && kickx < 850 && kicky < 850) {
arrayx = (kickx - 170) / 38.75f + 1.0f;
arrayy = (kicky - 170) / 38.75f + 1.0f;
std::cout << "arrayx=" << arrayx << " " << "arrayy=" << arrayy << std::endl;
if (chessboard[arrayx][arrayy].chesskind == 0) {
chessboard[arrayx][arrayy].chesskind = nowkind;
chess_draw_list[chess_number][0]=nowkind;
chess_draw_list[chess_number][1]=arrayx;
chess_draw_list[chess_number][2]=arrayy;
chess_number++;
if (judgewin(arrayx, arrayy) == 1) {
std::cout << "nowkind " << nowkind << " is win!!" << std::endl;
iswin = nowkind;
}
if (nowkind == 1)
nowkind = 2;
else
nowkind = 1;
}
}
break;
case 3:
if (chess_number > 0) {
chess_number--;
chessboard[chess_draw_list[chess_number][1]][chess_draw_list[chess_number][2]].chesskind = 0;
chess_draw_list[chess_number][0]=0;
chess_draw_list[chess_number][1]=0;
chess_draw_list[chess_number][2] = 0;
if (nowkind == 1)
nowkind = 2;
else
nowkind = 1;
}
break;
default:
break;
}
return;
}
int main() {
/**********part_mark**********/
#pragma region 初始化窗口
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(windowwide, windowhigh, "LearnOpenGL", nullptr, nullptr);
if (window == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
int win_width = windowwide, win_height = windowhigh;
glfwGetFramebufferSize(window, &win_width, &win_height);
glViewport(0, 0, win_width, win_height);
#pragma endregion
/**********part_mark**********/
startup();
/**********part_mark**********/
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
double timeValue = glfwGetTime();
render(timeValue);
glfwSwapBuffers(window);
if (iswin == 1) {
MessageBox(0, TEXT("黑棋胜利!!"), TEXT("result"), 0);
iswin = 0;
for (;chess_number > 0;) {
if (chess_number > 0) {
chess_number--;
chessboard[chess_draw_list[chess_number][1]][chess_draw_list[chess_number][2]].chesskind = 0;
chess_draw_list[chess_number][0] = 0;
chess_draw_list[chess_number][1] = 0;
chess_draw_list[chess_number][2] = 0;
}
}
}
else if (iswin == 2) {
MessageBox(0, TEXT("白棋胜利!!"), TEXT("result"), 0);
iswin = 0;
for (;chess_number > 0;) {
if (chess_number > 0) {
chess_number--;
chessboard[chess_draw_list[chess_number][1]][chess_draw_list[chess_number][2]].chesskind = 0;
chess_draw_list[chess_number][0] = 0;
chess_draw_list[chess_number][1] = 0;
chess_draw_list[chess_number][2] = 0;
}
}
}
}
/**********part_mark**********/
shutdown();
glfwTerminate();
return 0;
}
void startup() {
compile_shader();
rendering_program1 = linkprogram1();
rendering_program2 = linkprogram2();
glCreateVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
glPatchParameteri(GL_PATCH_VERTICES, 4);//是在这里,只设定一次吗? 好像是
glLineWidth(3.0);
glPointSize(25.0);
}
void render(double currentTime) {
static const GLfloat red[] = { 0.2f,0.3f,0.4f,1.0f };
static const GLfloat black[] = { 0.2f,0.2f,0.2f,1.0f };
static const GLfloat white[] = { 0.5f,0.5f,0.5f,1.0f };
if (iswin == 0) {
glClearBufferfv(GL_COLOR, 0, red);
}
else if (iswin == 1) {
glClearBufferfv(GL_COLOR, 0, black);
}
else if (iswin == 2) {
glClearBufferfv(GL_COLOR, 0, white);
}
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glUseProgram(rendering_program1);
glDrawArrays(GL_PATCHES, 0, 4);
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
glUseProgram(rendering_program2);
for (int i = 0;i < chess_number;i++) {
GLfloat a[4] = { chess_draw_list[i][0],chess_draw_list[i][1],chess_draw_list[i][2],0.0f };
glVertexAttrib4fv(0, a);
glDrawArrays(GL_POINTS, 0, 1);
}
}
void shutdown() {
delete_shader();
glDeleteVertexArrays(1, &vertex_array_object);
glDeleteProgram(rendering_program1);
glDeleteProgram(rendering_program2);
glDeleteVertexArrays(1, &vertex_array_object);//为什么要删除两次??
}
void compile_shader(void) {
#pragma region 编辑着色器内容
static const GLchar* vertex_shader_source[] = {
"#version 450 core \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[4]=vec4[4](vec4(0.7,0.7,0.5,1.0), \n"
" vec4(0.7,-0.7,0.5,1.0), \n"
" vec4(-0.7,-0.7,0.5,1.0), \n"
" vec4(-0.7,0.7,0.5,1.0)); \n"
" gl_Position = vertices[gl_VertexID]; \n"
"} \n"
};
static const GLchar* tess_control_shader_source[] = {
"#version 450 core \n"
"layout (vertices=4) out; \n"
"void main(void) \n"
"{ \n"
" if(gl_InvocationID==0){ \n"
" gl_TessLevelInner[0]=18.0; \n"
" gl_TessLevelInner[1]=18.0; \n"
" gl_TessLevelOuter[0]=18.0; \n"
" gl_TessLevelOuter[1]=18.0; \n"
" gl_TessLevelOuter[2]=18.0; \n"
" gl_TessLevelOuter[3]=18.0; \n"
" } \n"
" gl_out[gl_InvocationID].gl_Position=gl_in[gl_InvocationID].gl_Position;\n"
"} \n"
};
static const GLchar* tess_evaluation_shader_source[] = {
"#version 450 core \n"
"layout (quads,equal_spacing,ccw)in; \n"
"void main(void) \n"
"{ \n"
// " gl_Position=(gl_TessCoord.x*gl_in[0].gl_Position+ \n"
// " gl_TessCoord.y*gl_in[1].gl_Position+ \n"
// " gl_TessCoord.z*gl_in[2].gl_Position); \n"
这不适用于四边形
" float u = gl_TessCoord.x; \n"
" float v = gl_TessCoord.y; \n"
" float omu = 1-u; \n"
" float omv = 1-v; \n"
" gl_Position = \n"
" omu *omv *gl_in[0].gl_Position+ \n"
" u *omv *gl_in[1].gl_Position+ \n"
" u *v *gl_in[2].gl_Position+ \n"
" omu *v *gl_in[3].gl_Position; \n"
"} \n"
};
static const GLchar* geometry_shader_source[] = {
"#version 450 core \n"
"layout (triangles) in; \n"
"layout (line_strip,max_vertices=8) out; \n"
"void main(void) \n"
"{ \n"
"if(gl_in[0].gl_Position.x<0.5){ \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
" gl_Position=gl_in[0].gl_Position+vec4(0.1,0.0,0.0,0.0);EmitVertex(); \n"
"}else{ \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
"} \n"
"if(gl_in[0].gl_Position.x>-0.5){ \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
" gl_Position=gl_in[0].gl_Position+vec4(-0.1,0.0,0.0,0.0);EmitVertex(); \n"
"}else{ \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
"} \n"
"if(gl_in[0].gl_Position.y<0.5){ \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
" gl_Position=gl_in[0].gl_Position+vec4(0.0,0.1,0.0,0.0);EmitVertex(); \n"
"}else{ \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
"} \n"
"if(gl_in[0].gl_Position.y>-0.5){ \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
" gl_Position=gl_in[0].gl_Position+vec4(0.0,-0.1,0.0,0.0);EmitVertex(); \n"
"}else{ \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
" gl_Position=gl_in[0].gl_Position;EmitVertex(); \n"
"} \n"
"} \n"
};
static const GLchar* fragment_shader_source[] = {
"#version 450 core \n"
"out vec4 color; \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.9,0.9,0.8,1.0); \n"
"} \n"
};
static const GLchar* vertex_shader_source2[] = {
"#version 450 core \n"
"layout(location = 0) in vec4 a; \n"
"out vec4 vscolor; \n"
"void main(void) \n"
"{ \n"
" float x = 0.0; \n"
" float y = 0.0; \n"
" x = (a.y - 9) * 0.7 / 9.0; \n"
" y = (-a.z + 9) * 0.7 / 9.0; \n"
" gl_Position = vec4(x, y, 0.5, 1.0); \n"
" if ((a.x -1.0)<0.001&&(a.x -1.0)>-0.001) { \n"
" vscolor = vec4(0.0,0.0,0.0,1.0); \n"
" } \n"
" else if ((a.x -2.0)<0.001&&(a.x -2.0)>-0.001) {\n"
" vscolor = vec4(1.0, 1.0, 1.0, 1.0); \n"
" } \n"
" else { \n"
" vscolor = vec4(1.0, 0.0, 0.0, 1.0); \n"
" } \n"
"} \n"
};
static const GLchar* fragment_shader_source2[] = {
"#version 450 core \n"
"in vec4 vscolor;//黑为1白为0 \n"
"out vec4 color; \n"
"void main(void) \n"
"{ \n"
" color = vscolor; \n"
"} \n"
};
#pragma endregion
#pragma region 编译各种着色器并检查情况
GLint shader_success;
GLchar infoLog[512];//定义一个整型变量来表示是否成功编译,还定义了一个储存错误消息(如果有的话)的容器。
vs[0] = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs[0], 1, vertex_shader_source, NULL);
glCompileShader(vs[0]);
glGetShaderiv(vs[0], GL_COMPILE_STATUS, &shader_success);//检查编译是否成功
if (!shader_success)
{
glGetShaderInfoLog(vs[0], 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
vs[1] = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs[1], 1, vertex_shader_source2, NULL);
glCompileShader(vs[1]);
glGetShaderiv(vs[1], GL_COMPILE_STATUS, &shader_success);//检查编译是否成功
if (!shader_success)
{
glGetShaderInfoLog(vs[1], 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
fs[0] = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs[0], 1, fragment_shader_source, NULL);//试试这个是否有格子花纹
glCompileShader(fs[0]);
glGetShaderiv(fs[0], GL_COMPILE_STATUS, &shader_success);//检查编译是否成功
if (!shader_success)
{
glGetShaderInfoLog(fs[0], 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
fs[1] = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs[1], 1, fragment_shader_source2, NULL);
glCompileShader(fs[1]);
glGetShaderiv(fs[1], GL_COMPILE_STATUS, &shader_success);//检查编译是否成功
if (!shader_success)
{
glGetShaderInfoLog(fs[1], 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
tcs[0] = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(tcs[0], 1, tess_control_shader_source, NULL);
glCompileShader(tcs[0]);
glGetShaderiv(tcs[0], GL_COMPILE_STATUS, &shader_success);//检查编译是否成功
if (!shader_success)
{
glGetShaderInfoLog(tcs[0], 512, NULL, infoLog);
std::cout << "ERROR::SHADER::TESS_CONTROL::COMPILATION_FAILED\n" << infoLog << std::endl;
}
tes[0] = glCreateShader(GL_TESS_EVALUATION_SHADER);
glShaderSource(tes[0], 1, tess_evaluation_shader_source, NULL);
glCompileShader(tes[0]);
glGetShaderiv(tes[0], GL_COMPILE_STATUS, &shader_success);//检查编译是否成功
if (!shader_success)
{
glGetShaderInfoLog(tes[0], 512, NULL, infoLog);
std::cout << "ERROR::SHADER::TESS_EVALUATION::COMPILATION_FAILED\n" << infoLog << std::endl;
}
gs[0] = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(gs[0], 1, geometry_shader_source, NULL);
glCompileShader(gs[0]);
glGetShaderiv(gs[0], GL_COMPILE_STATUS, &shader_success);//检查编译是否成功
if (!shader_success)
{
glGetShaderInfoLog(gs[0], 512, NULL, infoLog);
std::cout << "ERROR::SHADER::GEOMETRY_SHADER::COMPILATION_FAILED\n" << infoLog << std::endl;
}
#pragma endregion
return;
}
void delete_shader(void){
int i=0;
for(i=0;i<3;i++){
if(vs[i]!=0)
glDeleteShader(vs[i]);
if(tcs[i]!=0)
glDeleteShader(tcs[i]);
if(tes[i]!=0)
glDeleteShader(tes[i]);
if(gs[i]!=0)
glDeleteShader(gs[i]);
if(fs[i]!=0)
glDeleteShader(fs[i]);
}
return;
}
GLuint linkprogram1(void){
GLuint program = glCreateProgram();
glAttachShader(program,vs[0]);
glAttachShader(program,tcs[0]);
glAttachShader(program,tes[0]);
glAttachShader(program,gs[0]);
glAttachShader(program,fs[0]);
glLinkProgram(program);
GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
GLchar* m_infor = new GLchar[1024];
glGetProgramInfoLog(program, 1023, NULL, m_infor);
std::cout << "ERROR_IN: program " << std::endl << "\tError in link program " << program << std::endl;
std::cout << "ERROR_IN: program " << std::endl << "\terror message : " << std::endl << m_infor << std::endl;
delete []m_infor ;
return 0;
}
return program;
}
GLuint linkprogram2(void){
GLuint program = glCreateProgram();
glAttachShader(program,vs[1]);
//glAttachShader(program,tcs[1]);
//glAttachShader(program,tes[1]);
//glAttachShader(program,gs[1]);
glAttachShader(program,fs[1]);
glLinkProgram(program);
GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
GLchar* m_infor = new GLchar[1024];
glGetProgramInfoLog(program, 1023, NULL, m_infor);
std::cout << "ERROR_IN: program " << std::endl << "\tError in link program " << program << std::endl;
std::cout << "ERROR_IN: program " << std::endl << "\terror message : " << std::endl << m_infor << std::endl;
delete []m_infor;
return 0;
}
return program;
}
GLint judgewin(GLint x, GLint y) {
GLint result = 0;
GLint same = 1;
GLint direction = 0;
int i = x, j = y;
//水平方向判定
i = x; j = y; same = 1; direction = 0;
while (1) {
if (direction == 0) {
i++;
if (i >= 0 && i <= 16) {
if (chessboard[i][j].chesskind == chessboard[i - 1][j].chesskind)
same++;
else {
direction = 1;
i = x;
j = y;
}
}
else {
direction = 1;
i = x;
j = y;
}
}
else {
i--;
if (i >= 0 && i <= 16) {
if (chessboard[i][j].chesskind == chessboard[i + 1][j].chesskind)
same++;
else
break;
}
else
break;
}
}
if (same >= 5) {result= 1;}
//垂直方向判定
i = x; j = y; same = 1; direction = 0;
while (1) {
if (direction == 0) {
j++;
if (j >= 0 && j <= 16) {
if (chessboard[i][j].chesskind == chessboard[i][j-1].chesskind)
same++;
else {
direction = 1;
i = x;
j = y;
}
}
else {
direction = 1;
i = x;
j = y;
}
}
else {
j--;
if (j >= 0 && j <= 16) {
if (chessboard[i][j].chesskind == chessboard[i][j+1].chesskind)
same++;
else
break;
}
else
break;
}
}
if (same >= 5) {result = 1;}
//左上到右下
i = x; j = y; same = 1; direction = 0;
while (1) {
if (direction == 0) {
i++;j++;
if (i >= 0 && i <= 16&&j >= 0 && j <= 16) {
if (chessboard[i][j].chesskind == chessboard[i - 1][j-1].chesskind)
same++;
else {
direction = 1;
i = x;
j = y;
}
}
else {
direction = 1;
i = x;
j = y;
}
}
else {
i--;j--;
if (i >= 0 && i <= 16 && j >= 0 && j <= 16) {
if (chessboard[i][j].chesskind == chessboard[i + 1][j+1].chesskind)
same++;
else
break;
}
else
break;
}
}
if (same >= 5) { result = 1; }
//右上到左下
i = x; j = y; same = 1; direction = 0;
while (1) {
if (direction == 0) {
i++;j--;
if (i >= 0 && i <= 16 && j >= 0 && j <= 16) {
if (chessboard[i][j].chesskind == chessboard[i - 1][j + 1].chesskind)
same++;
else {
direction = 1;
i = x;
j = y;
}
}
else {
direction = 1;
i = x;
j = y;
}
}
else {
i--;j++;
if (i >= 0 && i <= 16 && j >= 0 && j <= 16) {
if (chessboard[i][j].chesskind == chessboard[i + 1][j - 1].chesskind)
same++;
else
break;
}
else
break;
}
}
if (same >= 5) { result = 1; }
return result;
}