Cpp Char Type-checking Functions

isdigit是一个C语言中的标准库函数,用于检查给定字符是否为数字(0-9)。该函数定义在<ctype.h>头文件中,返回值为非零表示字符是数字,零则表示不是。注意,如果字符值无法表示为无符号字符且不等于EOF,其行为未定义。此函数不受当前C locale影响,仅判断0-9的ASCII值。

isdigit

 

C

Strings library

Null-terminated byte strings

 

Defined in header <ctype.h>

  

int isdigit( int ch );

  
   

Checks if the given character is a numeric character (0123456789).

The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF.

Parameters

ch-character to classify

Return value

Non-zero value if the character is a numeric character, zero otherwise.

Notes

isdigit and isxdigit are the only standard narrow character classification functions that are not affected by the currently installed C locale, although some implementations (e.g. Microsoft in 1252 codepage) may classify additional single-byte characters as digits.

Example

Run this code

#include <stdio.h>
#include <ctype.h>
#include <limits.h>
 
int main(void)
{
    for (int ndx=0; ndx<=UCHAR_MAX; ndx++)
        if (isdigit(ndx)) printf("%c", ndx);
    printf("\n");
}

Output:

0123456789

References

  • C11 standard (ISO/IEC 9899:2011):
  • 7.4.1.5 The isdigit function (p: 201)
  • C99 standard (ISO/IEC 9899:1999):
  • 7.4.1.5 The isdigit function (p: 182)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 4.3.1.4 The isdigit function

See also

iswdigit

(C95)

checks if a wide character is a digit
(function)

C++ documentation for isdigit

ASCII valuescharacters

iscntrl
iswcntrl

isprint
iswprint

isspace
iswspace

isblank
iswblank

isgraph
iswgraph

ispunct
iswpunct

isalnum
iswalnum

isalpha
iswalpha

isupper
iswupper

islower
iswlower

isdigit
iswdigit

isxdigit
iswxdigit

decimalhexadecimaloctal
0–8\x0\x8\0\10control codes (NUL, etc.)≠000000000000
9\x9\11tab (\t)≠00≠0≠000000000
10–13\xA\xD\12\15whitespaces (\n\v\f\r)≠00≠0000000000
14–31\xE\x1F\16\37control codes≠000000000000
32\x20\40space0≠0≠0≠000000000
33–47\x21\x2F\41\57!"#$%&'()*+,-./0≠000≠0≠0000000
48–57\x30\x39\60\7101234567890≠000≠00≠0000≠0≠0
58–64\x3A\x40\72\100:;<=>?@0≠000≠0≠0000000
65–70\x41\x46\101\106ABCDEF0≠000≠00≠0≠0≠000≠0
71–90\x47\x5A\107\132GHIJKLMNOP
QRSTUVWXYZ
0≠000≠00≠0≠0≠0000
91–96\x5B\x60\133\140[\]^_`0≠000≠0≠0000000
97–102\x61\x66\141\146abcdef0≠000≠00≠0≠00≠00≠0
103–122\x67\x7A\147\172ghijklmnop
qrstuvwxyz
0≠000≠00≠0≠00≠000
123–126\x7B\x7E\172\176{|}~0≠000≠0≠0000000
127\x7F\177backspace character (DEL)≠000000000000
//实验3 - 1第1题 #include <glad/glad.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <iostream> #include "Shader.h" //加载纹理数据需要的头文件 #define STB_IMAGE_IMPLEMENTATION #include <SOIL2/SOIL2.h> //文件图像加载库 void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow* window); void init(); void render(); void cleanUp(); const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; unsigned int texture1, texture2; unsigned int VBO, VAO, EBO; GLFWwindow* window = NULL; Shader* ourShader = NULL; int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X #endif //创建GLFW窗口对象 window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Lab3-1:3", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); //加载glad库 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } init(); //调用自定义的初始化函数 while (!glfwWindowShouldClose(window)) //窗口消息循环 { processInput(window); //窗口消息处理 render(); //调用自定义的渲染函数 glfwPollEvents(); //窗口消息轮询 glfwSwapBuffers(window); //窗口缓冲区交换 } cleanUp(); //调用自定义的资源释放函数 glfwTerminate(); //窗口销毁 return 0; } void init() { float vertices[] = { //位置 // 颜色 // 纹理坐标 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // 右下 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, // 右上 -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // 左下 -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // 左上 }; unsigned int indices[] = { //EBO索引 0, 3, 1, // first triangle 1, 3, 2 // second triangle }; //创建VAO,VBO,EBO对象 glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); //绑定VAO,VBO,EBO对象,并拷贝数据 glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //顶点位置属性 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); //顶点颜色属性 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); //顶点纹理坐标属性 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); //加载纹理1 glGenTextures(1, &texture1); glBindTexture(GL_TEXTURE_2D, texture1); //将纹理环绕设置为 GL_REPEAT glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //将纹理过滤设置为 GL_LINEAR glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //加载并生成纹理 int width, height, nrChannels; unsigned char* data = SOIL_load_image("lab3-1-3-1.jpg", &width, &height, &nrChannels, SOIL_LOAD_AUTO); if (data) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); } else { std::cout << "Failed to load texture" << std::endl; } //释放图像的内存 SOIL_free_image_data(data); //加载纹理2 glGenTextures(1, &texture2); glBindTexture(GL_TEXTURE_2D, texture2); //将纹理环绕设置为 GL_REPEAT glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //将纹理过滤设置为 GL_LINEAR glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3); //加载并生成纹理 data = SOIL_load_image("lab3-1-3-2.png", &width, &height, &nrChannels, SOIL_LOAD_AUTO); if (data) { //PNG图片有透明通道,所以纹理格式要设置为GL_RGBA glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); } else { std::cout << "Failed to load texture" << std::endl; } //释放图像的内存 SOIL_free_image_data(data); //glGenerateMipmap(GL_TEXTURE_2D); //创建着色器对象 ourShader = new Shader("lab3-1-3.vs", "lab3-1-3.fs"); //注意着色器文件路径 ourShader->use(); // 使用着色器程序 ourShader->setInt("texture1", 0); //设置uniform采样器 ourShader->setInt("texture2", 1); } void cleanUp() //释放资源 { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glDeleteTextures(1, &texture1); glDeleteTextures(1, &texture2); if (ourShader) { delete ourShader; } } void render() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //窗口背景色 glClear(GL_COLOR_BUFFER_BIT); //清除窗口颜色缓冲 glActiveTexture(GL_TEXTURE0); //激活纹理单元0 glBindTexture(GL_TEXTURE_2D, texture1); //绑定纹理1 glActiveTexture(GL_TEXTURE1); //激活纹理单元1 glBindTexture(GL_TEXTURE_2D, texture2); //绑定纹理2 //激活着色器 glm::mat4 transform = glm::mat4(1.0f); //变换 unsigned int transformLoc = glGetUniformLocation(ourShader->ID, "transform"); glUniformMatrix4fv(transformLoc, 1, GL_FALSE, &transform[0][0]); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { //设置视口大小与窗口尺寸匹配 glViewport(0, 0, width, height); } #pragma once //#ifndef SHADER_H //#define SHADER_H #include <glad/glad.h> #include <glm/glm.hpp> #include <string> #include <fstream> #include <sstream> #include <iostream> class Shader { public: unsigned int ID; Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr) { // 1. retrieve the vertex/fragment source code from filePath std::string vertexCode; std::string fragmentCode; std::string geometryCode; std::ifstream vShaderFile; std::ifstream fShaderFile; std::ifstream gShaderFile; // ensure ifstream objects can throw exceptions: vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { // open files vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; // read file's buffer contents into streams vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // close file handlers vShaderFile.close(); fShaderFile.close(); // convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); // if geometry shader path is present, also load a geometry shader if (geometryPath != nullptr) { gShaderFile.open(geometryPath); std::stringstream gShaderStream; gShaderStream << gShaderFile.rdbuf(); gShaderFile.close(); geometryCode = gShaderStream.str(); } } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; } const char* vShaderCode = vertexCode.c_str(); const char * fShaderCode = fragmentCode.c_str(); unsigned int vertex, fragment; // vertex shader vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); checkCompileErrors(vertex, "VERTEX"); // fragment Shader fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); checkCompileErrors(fragment, "FRAGMENT"); // if geometry shader is given, compile geometry shader unsigned int geometry; if (geometryPath != nullptr) { const char * gShaderCode = geometryCode.c_str(); geometry = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(geometry, 1, &gShaderCode, NULL); glCompileShader(geometry); checkCompileErrors(geometry, "GEOMETRY"); } // shader Program ID = glCreateProgram(); glAttachShader(ID, vertex); glAttachShader(ID, fragment); if (geometryPath != nullptr) glAttachShader(ID, geometry); glLinkProgram(ID); checkCompileErrors(ID, "PROGRAM"); // delete the shaders as they're linked into our program now and no longer necessery glDeleteShader(vertex); glDeleteShader(fragment); if (geometryPath != nullptr) glDeleteShader(geometry); } // activate the shader // ------------------------------------------------------------------------ void use() { glUseProgram(ID); } // utility uniform functions // ------------------------------------------------------------------------ void setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); } // ------------------------------------------------------------------------ void setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setVec2(const std::string &name, const glm::vec2 &value) const { glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec2(const std::string &name, float x, float y) const { glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); } // ------------------------------------------------------------------------ void setVec3(const std::string &name, const glm::vec3 &value) const { glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec3(const std::string &name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); } // ------------------------------------------------------------------------ void setVec4(const std::string &name, const glm::vec4 &value) const { glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec4(const std::string &name, float x, float y, float z, float w) { glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); } // ------------------------------------------------------------------------ void setMat2(const std::string &name, const glm::mat2 &mat) const { glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ void setMat3(const std::string &name, const glm::mat3 &mat) const { glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ void setMat4(const std::string &name, const glm::mat4 &mat) const { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } private: // utility function for checking shader compilation/linking errors. // ------------------------------------------------------------------------ void checkCompileErrors(GLuint shader, std::string type) { GLint success; GLchar infoLog[1024]; if (type != "PROGRAM") { glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } else { glGetProgramiv(shader, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } } }; //#endif无法打开 源 文件 "Shader.h" 未定义标识符 "Shader" 应输入类型说明符
10-18
#ifndef COLORHEXAGON_H #define COLORHEXAGON_H #include <glad/glad.h> #include <glm/glm.hpp> // 顶点结构:位置 + 颜色 struct HexVertex2 { glm::vec3 position; glm::vec3 color; }; class ColorHexagon { public: ColorHexagon(); ~ColorHexagon(); void initData(); // 初始化顶点数据和 VAO/VBO void renderObject(); // 渲染六边形,绑定调用 private: GLuint VAO, VBO; }; #endif // COLORHEXAGON_H #ifndef COLORTRIANGLE_H #define COLORTRIANGLE_H #include <glad/glad.h> class ColorTriangle { public: ColorTriangle(); ~ColorTriangle(); void render(); private: GLuint VAO; GLuint VBO; GLuint shaderProgram; void initShader(); void initBuffers(); }; #endif // COLORTRIANGLE_H #ifndef DEMO_H_ #define DEMO_H_ #include <glad/glad.h> class Demo { public: Demo(); ~Demo(); private: bool enableCullFace; //是否启用面剔除功能(即不渲染背对摄像机的面) GLenum cullMode; //指定要剔除的面类型:GL_BACK(背面)、GL_FRONT(前面)或 GL_FRONT_AND_BACK(双面) GLenum frontFace; //定义三角形的“正面”方向:GL_CCW(逆时针为正,默认),GL_CW(顺时针为正) protected: const char* vertexShaderSource; //顶点着色器的 GLSL 源代码字符串 const char* fragmentShaderSource; //默认片段着色器的 GLSL 源代码字符串 const char* fragmentShader1Source; //可选的第二种片段着色器源码(例如不同光照模型) const char* fragmentShader2Source; //可选的第三种片段着色器源码(例如边缘检测、颜色变换等) public: virtual void setRenderParameter(bool enableCullFace = false, GLenum cullMode = GL_FRONT, GLenum frontFace = GL_CCW); //补注释 virtual void beginRender(); // 开始渲染前调用,用于应用当前设置的渲染状态(如启用/禁用面剔除) virtual void render() = 0; // 纯虚函数:子类必须实现具体的渲染逻辑(如绘制几何体、使用着色器等) }; #endif #pragma once #include "Rectangle.h" #include "Demo.h" class Demo3_2:public Demo { public: Demo3_2(); ~Demo3_2(); private: Rectangle rect; //表示一个具体的矩形对象实例 // 注释:该成员变量封装了顶点数据、缓冲区(VBO/VAO)、着色器以及绘制逻辑在 render() 中会被调用来实际绘制矩形 public: void render(); //重写基类的纯虚函数,实现本 demo 的具体渲染逻辑 // 注释:在此函数中会调用 beginRender() 设置 OpenGL 状态,然后调用 rect.render() 执行矩形的绘制操作 }; #pragma once #include "FivePointedStar.h" #include "Demo.h" class Demo3_3 :public Demo { public: Demo3_3(); ~Demo3_3(); private: FivePointedStar fivePointedStar; //表示一个五角星对象实例 // 注释:该成员封装了五角星的顶点数据、缓冲对象(VBO/VAO)以及渲染逻辑。在 render() 中将调用其自身的 render 方法进行绘制 public: void render(); //重写基类的纯虚函数,实现本 demo 的具体渲染行为 // 注释:在此函数中首先调用 beginRender() 设置 OpenGL 状态(如面剔除)然后调用 fivePointedStar.render() 来实际绘制五角星 }; #pragma once #include "Object.h" #include <GLFW/glfw3.h> #include <glm/glm.hpp> class FivePointedStar : public Object { public: FivePointedStar(); ~FivePointedStar(); private: float x; //五角星中心点的 X 坐标 float y; //五角星中心点的 Y 坐标 double t; //当前时间(或累计动画时间),用于控制动画状态(如旋转角度随时间变化) float rotateSpeed; //旋转速度,决定五角星绕自身中心旋转的快慢 ColorVertex fivePointedStar[12]; //存储构成五角星的 12 个顶点数据 // 注释:每个顶点包含位置 (x, y) 和颜色 (r, g, b)使用三角扇(GL_TRIANGLE_FAN)方式连接,形成封闭五角星 public: virtual void initData(); //初始化顶点数据:设置五角星的几何形状、初始颜色、中心位置等 // 在 OpenGL 中通常也负责创建并绑定 VAO/VBO,上传初始顶点数据到 GPU virtual void update(float dt) {} //更新动画状态:根据时间增量 dt 更新内部参数 virtual void renderObject(); //执行实际绘制操作:绑定着色器、VAO,并调用 glDrawArrays(GL_TRIANGLE_FAN, 0, 12)实现五角星在屏幕上的渲染 void updateDataBuffer(); //将更新后的顶点数据(如旋转后的新坐标)重新上传到 GPU 的 VBO 缓冲区用于支持动态变形或动画效果(如持续旋转) void calcData(); //根据当前状态(x, y, t, rotateSpeed 等)重新计算五角星各个顶点的坐标和颜色是生成五角星几何结构的核心函数,通常被 initData() 和 update() 调用 }; // Hexagon.h #pragma once #include "Object.h" #include <glm/glm.hpp> struct HexVertex { glm::vec3 position; glm::vec3 color; }; class Hexagon { private: unsigned int VAO, VBO; public: Hexagon(); ~Hexagon(); void initData(); // 用于初始化六边形的顶点数据并上传至 GPU。 void renderObject(); // 用于执行绘制命令。 void updateDataBuffer(); //声明一个更新缓冲区数据的函数。 }; // Hexagon2.h #pragma once #include "Object.h" #include <glm/glm.hpp> struct Hex2Vertex { glm::vec3 position; glm::vec3 color; }; class Hexagon2 { private: unsigned int VAO, VBO; public: Hexagon2(); ~Hexagon2(); void initData(); // 用于初始化六边形的顶点数据并上传至 GPU。 void renderObject(); // 用于执行绘制命令。 void updateDataBuffer(); //声明一个更新缓冲区数据的函数。 }; #pragma once #include "Demo.h" #include "Triangle.h" class Lab3_2:public Demo { public: Lab3_2(); ~Lab3_2(); private: Triangle leftTriangle; //左侧三角形对象实例 // 注释:封装了左侧三角形的顶点数据、颜色、VBO/VAO 及其渲染逻辑在 render() 中会被调用以绘制位于屏幕左侧的三角形 Triangle rightTriangle; //右侧三角形对象实例 // 注释:与 leftTriangle 类似,但可能具有不同的顶点位置或颜色用于对比测试面剔除(Culling)对不同朝向三角形的影响 bool enableCullFace; //是否启用背面剔除功能的开关标志 // 注释:若为 true,则调用 glEnable(GL_CULL_FACE);否则调用 glDisable(GL_CULL_FACE)控制是否剔除不可见面(提升性能并观察渲染效果变化) GLenum cullMode; //指定要剔除的面(正面或背面) //可取值:GL_BACK -> 剔除背面 // GL_FRONT -> 剔除正面 // GL_FRONT_AND_BACK -> 正反面都剔除(整个物体不可见) // 该值将传递给 glCullFace(cullMode) GLenum frontFace; // 定义哪一侧为“正面”(顺时针或逆时针) //可取值:GL_CCW -> 逆时针方向的多边形被视为正面(默认) // GL_CW -> 顺时针方向的多边形被视为正面 // 该值将传递给 glFrontFace(frontFace),影响面剔除判断结果 public: void render(); //重写基类的纯虚函数,执行本实验的具体渲染流程 // 注释:在此函数中: // 1. 调用 beginRender() 设置全局渲染状态 // 2. 根据 enableCullFace 决定是否启用面剔除 // 3. 设置 cullMode 和 frontFace // 4. 分别调用 leftTriangle.render() 和 rightTriangle.render() 绘制两个三角形 }; #pragma once #include <string> #include <glad/glad.h> #include <glm/glm.hpp> #include "Shader.h" using namespace std; typedef struct { float x; float y; float z; }Vertex; //表示三维空间中的一个点,仅包含位置坐标 (x, y, z) typedef struct { glm::vec3 coordinate; glm::vec4 color; } ColorVertex; //包含位置和颜色数据的顶点,用于支持逐顶点着色 class Object { public: Object(); Object(const char* vs, const char* fs);//构造函数重载:传入顶点着色器和片段着色器路径来创建着色器 virtual ~Object(); public: void createShader(const char* vs, const char* fs); // 创建并编译着色器程序,输入为顶点和片段着色器文件路径 protected: GLvoid* vertices; //指向顶点数据的指针(可以是 Vertex 或 ColorVertex 数组),将被上传到 GPU 的 VBO GLuint verticesSize; //顶点数据的总字节数(例如:sizeof(ColorVertex) * 顶点数量) GLuint indexSize; //索引数组的元素个数(用于 EBO 绘制时指定索引数量) GLuint VBO, VAO, EBO; //OpenGL 缓冲对象标识符 Shader* shader; //指向使用的着色器程序对象,用于在渲染时激活着色器 protected: GLsizei stride; void createBuffer(GLsizei stride,GLenum ussage); //创建并初始化 VAO/VBO/EBO 缓冲区 // stride: 每个顶点的字节大小,用于 glVertexAttribPointer 设置步长 // usage: 数据使用方式(如 GL_STATIC_DRAW, GL_DYNAMIC_DRAW) public: virtual void initData() = 0; //纯虚函数:子类必须实现,用于初始化顶点和索引数据 virtual void render(); //提供默认实现:绑定着色器 -> 更新数据 -> 渲染对象 virtual void update(float dt) = 0; //纯虚函数:每帧更新逻辑(如动画、变换),dt 为时间增量 virtual void updateDataBuffer(); //可选实现:更新 VBO 中的数据(用于动态变化的顶点) virtual void renderObject() = 0; //纯虚函数:具体渲染调用(如 glDrawArrays 或 glDrawElements) virtual void setShaderString(const char* vs, const char* fs); // 设置新的着色器源文件路径(可重新加载着色器) }; #pragma once #include "Object.h" class Rectangle : public Object { public: Rectangle(); ~Rectangle(); private: float x; //矩形中心点(或左下角)的 X 坐标 float y; //矩形中心点(或左下角)的 Y 坐标 // 注释:具体是中心还是角落取决于顶点生成方式,在 initData() 中确定 public: virtual void initData(); //初始化矩形的顶点数据和 OpenGL 资源 // 功能包括: // - 计算四个顶点(或两个三角形共6个顶点)的坐标 // - 创建并配置 VAO、VBO // - 将顶点数据上传到 GPU 缓冲区 // - 可能设置默认颜色或纹理坐标 virtual void update(float dt) {} // 更新逻辑回调函数(当前为空实现) // 注释:用于处理动画或状态变化(如移动、缩放) // 可在此处更新 x, y 实现平移,然后调用 calcData 或 updateDataBuffer // 默认不执行任何操作,子类可根据需要重写 virtual void renderObject(); //执行矩形的实际绘制操作 // 功能包括: // - 绑定已创建的着色器程序 // - 绑定 VAO // - 调用 glDrawArrays(GL_TRIANGLES, 0, 6) 或 glDrawElements // - 渲染由两个三角形组成的矩形 }; #pragma once //#ifndef SHADER_H //#define SHADER_H #include <glad/glad.h> #include <glm/glm.hpp> #include <string> #include <fstream> #include <sstream> #include <iostream> class Shader { public: unsigned int ID; Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr) { // 1. retrieve the vertex/fragment source code from filePath std::string vertexCode; std::string fragmentCode; std::string geometryCode; std::ifstream vShaderFile; std::ifstream fShaderFile; std::ifstream gShaderFile; // ensure ifstream objects can throw exceptions: vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { // open files vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; // read file's buffer contents into streams vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // close file handlers vShaderFile.close(); fShaderFile.close(); // convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); // if geometry shader path is present, also load a geometry shader if (geometryPath != nullptr) { gShaderFile.open(geometryPath); std::stringstream gShaderStream; gShaderStream << gShaderFile.rdbuf(); gShaderFile.close(); geometryCode = gShaderStream.str(); } } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; } const char* vShaderCode = vertexCode.c_str(); const char * fShaderCode = fragmentCode.c_str(); unsigned int vertex, fragment; // vertex shader vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); checkCompileErrors(vertex, "VERTEX"); // fragment Shader fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); checkCompileErrors(fragment, "FRAGMENT"); // if geometry shader is given, compile geometry shader unsigned int geometry; if (geometryPath != nullptr) { const char * gShaderCode = geometryCode.c_str(); geometry = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(geometry, 1, &gShaderCode, NULL); glCompileShader(geometry); checkCompileErrors(geometry, "GEOMETRY"); } // shader Program ID = glCreateProgram(); glAttachShader(ID, vertex); glAttachShader(ID, fragment); if (geometryPath != nullptr) glAttachShader(ID, geometry); glLinkProgram(ID); checkCompileErrors(ID, "PROGRAM"); // delete the shaders as they're linked into our program now and no longer necessery glDeleteShader(vertex); glDeleteShader(fragment); if (geometryPath != nullptr) glDeleteShader(geometry); } // activate the shader // ------------------------------------------------------------------------ void use() { glUseProgram(ID); } // utility uniform functions // ------------------------------------------------------------------------ void setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); } // ------------------------------------------------------------------------ void setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setVec2(const std::string &name, const glm::vec2 &value) const { glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec2(const std::string &name, float x, float y) const { glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); } // ------------------------------------------------------------------------ void setVec3(const std::string &name, const glm::vec3 &value) const { glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec3(const std::string &name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); } // ------------------------------------------------------------------------ void setVec4(const std::string &name, const glm::vec4 &value) const { glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec4(const std::string &name, float x, float y, float z, float w) { glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); } // ------------------------------------------------------------------------ void setMat2(const std::string &name, const glm::mat2 &mat) const { glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ void setMat3(const std::string &name, const glm::mat3 &mat) const { glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ void setMat4(const std::string &name, const glm::mat4 &mat) const { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } private: // utility function for checking shader compilation/linking errors. // ------------------------------------------------------------------------ void checkCompileErrors(GLuint shader, std::string type) { GLint success; GLchar infoLog[1024]; if (type != "PROGRAM") { glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } else { glGetProgramiv(shader, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } } }; //#endif#pragma once #include <glad/glad.h> #include <string> #include <iostream> using namespace std; class Shader { public: unsigned int id; //着色器程序(Program Object)的唯一标识符(OpenGL ID) Shader() { id = 0; } Shader(const char* vs, const char* fs) { unsigned int vertex, fragment; //临时变量,分别存储顶点着色器和片段着色器的 OpenGL 对象 ID // 注释:- vertex: 通过 glCreateShader(GL_VERTEX_SHADER) 创建,- fragment: 通过 glCreateShader(GL_FRAGMENT_SHADER) 创建它们是独立编译的着色器单元,在链接前不会生效 vertex = glCreateShader(GL_VERTEX_SHADER); //创建一个顶点着色器对象,该对象将用于加载、编译顶点着色器源代码 fragment = glCreateShader(GL_FRAGMENT_SHADER); //创建一个片段着色器对象,用于处理像素颜色计算(光栅化后) id = glCreateProgram(); //创建一个着色器程序对象,所有着色器必须附加到此程序才能链接运行链接成功后,可通过 glUseProgram(id) 启用整个管线 glShaderSource(vertex, 1, &vs,nullptr); //将 C++ 字符串 vs(顶点着色器源码)绑定到 vertex 着色器对象 glCompileShader(vertex); //编译顶点着色器,将之前设置的源码编译成 GPU 可执行的形式,若语法错误则编译失败,需调用 checkCompileErrors 检查 checkCompileErrors(vertex, "VERTEX"); //检查顶点着色器是否编译成功如果失败,打印详细的错误日志到控制台 glShaderSource(fragment, 1, &fs, nullptr); //将 fs 字符串作为源码传入片段着色器对象 glCompileShader(fragment); //编译片段着色器 checkCompileErrors(fragment, "FRAGMENT"); //检查片段着色器编译状态 glAttachShader(id, vertex); //将已编译的顶点着色器附加到程序对象 id 上 glAttachShader(id, fragment); //将已编译的片段着色器附加到程序对象 id 上 glLinkProgram(id); //链接着色器程序把所有附加的着色器合并为一个可执行程序检查接口匹配性(如 vs 输出与 fs 输入)、全局符号等成功后方可使用 glDeleteShader(vertex); //链接完成后,删除临时的顶点着色器对象 glDeleteShader(fragment); // 删除临时的片段着色器对象 } void use() { glUseProgram(id); //激活当前着色器程序使 OpenGL 渲染管线使用这个 program 进行绘制后续 draw call 都会使用该着色器逻辑 } private: void checkCompileErrors(GLuint shader, std::string type) //用于检查着色器编译或程序链接是否出错 { GLint success; GLchar infoLog[1024]; if (type != "PROGRAM") { glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } else { glGetProgramiv(shader, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } } }; #pragma once #include "Object.h" class Triangle: public Object { public: Triangle(); ~Triangle(); public: virtual void initData() ; //虚函数:初始化与三角形相关的 GPU 数据(如顶点数组、缓冲对象 VAO/VBO) // 通常在此函数中: // - 创建并绑定 VAO 和 VBO // - 上传顶点数据到 GPU // - 配置顶点属性指针(vertex attribute pointers) // 子类可重写此函数以自定义初始化逻辑 virtual void update(float dt) {} //虚函数:更新三角形的逻辑状态,参数 dt 为帧间时间间隔(delta time),单位秒 // 虚函数:更新三角形的逻辑状态,参数 dt 为帧间时间间隔(delta time),单位秒 // 用于实现动画、变换矩阵更新等随时间变化的操作 // 当前为空实现({}),表示默认无需更新;子类可根据需要重写 virtual void renderObject(); //虚函数:执行三角形的渲染操作 // 通常包括: // - 激活着色器程序 // - 绑定 VAO // - 调用 glDrawArrays 或类似绘制命令 // 实现从 GPU 中绘制该三角形到屏幕的过程 void setData(Vertex* data, int size); //设置三角形的顶点数据 // 参数: // - Vertex* data: 指向顶点数据数组的指针(包含位置、颜色、纹理坐标等) // - int size: 顶点数量 // 功能:将 CPU 端的顶点数据传入 Triangle 对象,供后续上传至 GPU 使用 void setShaderString(const char* vs, const char* fs); //设置用于渲染三角形的着色器源码 // 参数: // - const char* vs: 顶点着色器(Vertex Shader)的源代码字符串 // - const char* fs: 片段着色器(Fragment Shader)的源代码字符串 // 功能:保存着色器代码,在初始化时用于创建和编译 Shader 程序 }; #pragma once #ifndef VERTEX_H #define VERTEX_H #include <glm/glm.hpp> struct ColorVertex { glm::vec3 coordinate; glm::vec4 color; }; #endif // VERTEX_H #pragma once #ifndef WAVEHEXAGON_H #define WAVEHEXAGON_H #include <glad/glad.h> // 顶点结构:位置 + 颜色 struct HexVertex3 { float position[3]; float color[3]; // 颜色,用于在 shader 中调制 }; class WaveHexagon { public: WaveHexagon(); ~WaveHexagon(); void init(); // 初始化 VAO/VBO 和着色器 void render(); // 渲染并传入时间 uniform void destroy(); // 释放资源 private: GLuint VAO, VBO; GLuint shaderProgram; GLint uniTime; // uniform location: u_Time }; #endif // WAVEHEXAGON_H 这里是所有.h的头文件,.cpp的文件我现在再发给你
10-20
#pragma once //#ifndef SHADER_H //#define SHADER_H #include <glad/glad.h> #include <glm/glm.hpp> #include <string> #include <fstream> #include <sstream> #include <iostream> class Shader { public: unsigned int ID; Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr) { // 1. retrieve the vertex/fragment source code from filePath std::string vertexCode; std::string fragmentCode; std::string geometryCode; std::ifstream vShaderFile; std::ifstream fShaderFile; std::ifstream gShaderFile; // ensure ifstream objects can throw exceptions: vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { // open files vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; // read file's buffer contents into streams vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // close file handlers vShaderFile.close(); fShaderFile.close(); // convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); // if geometry shader path is present, also load a geometry shader if (geometryPath != nullptr) { gShaderFile.open(geometryPath); std::stringstream gShaderStream; gShaderStream << gShaderFile.rdbuf(); gShaderFile.close(); geometryCode = gShaderStream.str(); } } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; } const char* vShaderCode = vertexCode.c_str(); const char * fShaderCode = fragmentCode.c_str(); unsigned int vertex, fragment; // vertex shader vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); checkCompileErrors(vertex, "VERTEX"); // fragment Shader fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); checkCompileErrors(fragment, "FRAGMENT"); // if geometry shader is given, compile geometry shader unsigned int geometry; if (geometryPath != nullptr) { const char * gShaderCode = geometryCode.c_str(); geometry = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(geometry, 1, &gShaderCode, NULL); glCompileShader(geometry); checkCompileErrors(geometry, "GEOMETRY"); } // shader Program ID = glCreateProgram(); glAttachShader(ID, vertex); glAttachShader(ID, fragment); if (geometryPath != nullptr) glAttachShader(ID, geometry); glLinkProgram(ID); checkCompileErrors(ID, "PROGRAM"); // delete the shaders as they're linked into our program now and no longer necessery glDeleteShader(vertex); glDeleteShader(fragment); if (geometryPath != nullptr) glDeleteShader(geometry); } // activate the shader // ------------------------------------------------------------------------ void use() { glUseProgram(ID); } // utility uniform functions // ------------------------------------------------------------------------ void setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); } // ------------------------------------------------------------------------ void setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); } // ------------------------------------------------------------------------ void setVec2(const std::string &name, const glm::vec2 &value) const { glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec2(const std::string &name, float x, float y) const { glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); } // ------------------------------------------------------------------------ void setVec3(const std::string &name, const glm::vec3 &value) const { glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec3(const std::string &name, float x, float y, float z) const { glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); } // ------------------------------------------------------------------------ void setVec4(const std::string &name, const glm::vec4 &value) const { glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); } void setVec4(const std::string &name, float x, float y, float z, float w) { glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); } // ------------------------------------------------------------------------ void setMat2(const std::string &name, const glm::mat2 &mat) const { glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ void setMat3(const std::string &name, const glm::mat3 &mat) const { glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } // ------------------------------------------------------------------------ void setMat4(const std::string &name, const glm::mat4 &mat) const { glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); } private: // utility function for checking shader compilation/linking errors. // ------------------------------------------------------------------------ void checkCompileErrors(GLuint shader, std::string type) { GLint success; GLchar infoLog[1024]; if (type != "PROGRAM") { glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } else { glGetProgramiv(shader, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shader, 1024, NULL, infoLog); std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } } }; //#endif这是我的shader.h你看看
12-05
内容概要:本文系统阐述了Java Persistence API(JPA)的核心概念、技术架构、核心组件及实践应用,重点介绍了JPA作为Java官方定义的对象关系映射(ORM)规范,如何通过实体类、EntityManager、JPQL和persistence.xml配置文件实现Java对象与数据库表之间的映射与操作。文章详细说明了JPA解决的传统JDBC开发痛点,如代码冗余、对象映射繁琐、跨数据库兼容性差等问题,并解析了JPA与Hibernate、EclipseLink等实现框架的关系。同时提供了基于Hibernate和MySQL的完整实践案例,涵盖Maven依赖配置、实体类定义、CRUD操作实现等关键步骤,并列举了常用JPA注解及其用途。最后总结了JPA的标准化优势、开发效率提升能力及在Spring生态中的延伸应用。 适合人群:具备一定Java基础,熟悉基本数据库操作,工作1-3年的后端开发人员或正在学习ORM技术的中级开发者。 使用场景及目标:①理解JPA作为ORM规范的核心原理与组件协作机制;②掌握基于JPA+Hibernate进行数据库操作的开发流程;③为技术选型、团队培训或向Spring Data JPA过渡提供理论与实践基础。 阅读建议:此资源以理论结合实践的方式讲解JPA,建议读者在学习过程中同步搭建环境,动手实现文中示例代码,重点关注EntityManager的使用、JPQL语法特点以及注解配置规则,从而深入理解JPA的设计思想与工程价值。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值