#include “Cone.h”
Cone::Cone(std::string vert, std::string frag, std::string texName) :Object(vert, frag, texName)
{
}
Cone::~Cone()
{
}
void Cone::initData(DataParam *param)
{
dataParam = *param;
GLfloat radius = dataParam.radius;
GLuint longSegments = dataParam.longSegments;
//GLuint latSegments = param->latSegments;
GLfloat height = dataParam.height;
//float fPhi = glm::pi<float>() / latSegments; //纬度上角度差:Phi float fTheta = (glm::pi<float>() * 2.0f) / longSegments; //经度上角度差:Theta //生成顶点数据 verticesSize = 2 * (longSegments + 2);// *sizeof(TextureColorVertex); vertices = new TextureColorVertex[verticesSize]; verticesSize *= sizeof(TextureColorVertex); int start = 0; //生成侧面数据 vertices[start].coordinate.x = 0; vertices[start].coordinate.y = height / 2.0f; vertices[start].coordinate.z = 0; vertices[start].texture.s = 0.5; vertices[start].texture.t = 0.5; vertices[start].color.r = vertices[start].color.g = vertices[start].color.b = 1.0f; ++start; for (int i = start; i < start + longSegments + 1; i++) { vertices[i].coordinate.x = radius * cos(glm::pi<float>() * 2 - i * fTheta); vertices[i].coordinate.y = -height / 2.0f; vertices[i].coordinate.z = radius * sin(glm::pi<float>() * 2 - i * fTheta); vertices[i].texture.s = 0.5f + 0.5f * cos(glm::pi<float>() * 2 - i * fTheta); vertices[i].texture.t = 0.5f + 0.5f * sin(glm::pi<float>() * 2 - i * fTheta); vertices[i].color.r = vertices[i].color.g = vertices[i].color.b = 1.0f; } start += longSegments + 1; //生成下底顶点数据 vertices[start].coordinate.x = 0; vertices[start].coordinate.y = -height / 2.0f; vertices[start].coordinate.z = 0.0f; vertices[start].texture.s = 0.5f; vertices[start].texture.t = 0.5f; vertices[start].color.r = vertices[start].color.g = vertices[start].color.b = 1.0f; ++start; for (int i = start; i < start + longSegments + 1; i++) { vertices[i].coordinate.x = radius * cos(i * fTheta); vertices[i].coordinate.y = -height / 2.0f; vertices[i].coordinate.z = radius * sin(i * fTheta); vertices[i].texture.s = 0.5f + 0.5f * cos(i * fTheta); vertices[i].texture.t = 0.5f + 0.5f * sin(i * fTheta); vertices[i].color.r = vertices[i].color.g = vertices[i].color.b = 1.0f; } createBuffer(sizeof(TextureColorVertex)); delete[]vertices; revolutionAngle = 0.0f; rotationAngle = 0.0f; revolutionSpeed = 0.1f; rotationSpeed = 0.5f;
}
void Cone::renderObject()
{
glBindVertexArray(VAO);
GLint first = 0;
glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments + 2);
first += dataParam.longSegments + 2;
glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments + 2);
}
void Cone::update(float dt)
{
revolutionAngle += revolutionSpeed;
rotationAngle += rotationSpeed;
model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 0.0f, 1.0f));
model = glm::translate(model, glm::vec3(0.0f, 4.0f, 0.0f));
model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
}
#pragma once
#include “Object.h”
class Cone :public Object
{
public:
Cone(std::string vert, std::string frag, std::string texName = “”);
~Cone();
void initData(DataParam *param = nullptr); void renderObject(); void update(float dt);
private:
DataParam dataParam;
};
#include “Cube18.h”
Cube18::Cube18(std::string vert, std::string frag, std::string texName) :Object(vert, frag, texName)
{
}
Cube18::~Cube18()
{
}
void Cube18::initData(DataParam *param)
{
TextureColorVertex verticesData[] = {
// positions // colors // texture coords
//top
glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 0.0f), //0
glm::vec3(0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 1.0f), //1
glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 0.0f), //2
glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f), //3
//side glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(4.0f, 0.0f), //7// bottom right glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(4.0f, 1.0f), //6// top right glm::vec3(-0.5f, -0.5f,0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(3.0f, 0.0f), //5// bottom left glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(3.0f, 1.0f), //4// top left glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(2.0f, 0.0f), //8 glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(2.0f, 1.0f), //9 glm::vec3(0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f,0.0f), //10 glm::vec3(0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(1.0f,1.0f), //11 glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f), //12 glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(0.0f, 1.0f), //13 //bottom glm::vec3(0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f), //14 glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f), //15 glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 0.0f), //16 glm::vec3(-0.5f, -0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(0.0f, 1.0f) //17 }; vertices = new TextureColorVertex[18]; verticesSize = sizeof(verticesData);//sizeof(TextureColorVertex) * 18; memcpy(vertices, verticesData, verticesSize); createBuffer(sizeof(TextureColorVertex)); revolutionAngle = 0.0f; rotationAngle = 0.0f; revolutionSpeed = 5.0f; rotationSpeed = 0.5f;
}
void Cube18::renderObject()
{
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 10);
glDrawArrays(GL_TRIANGLE_STRIP, 14, 4);
}
void Cube18::update(float dt)
{
rotationAngle += rotationSpeed;
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(1.0f, 1.0f, 1.0f));
model = glm::scale(model, glm::vec3(3.0f, 3.0f, 3.0f));
}#pragma once
#include “Object.h”
class Cube18 :public Object
{
public:
Cube18(std::string vert, std::string frag, std::string texName = “”);
~Cube18();
void initData(DataParam *param = nullptr); void renderObject(); void update(float dt);
};
#include “Cylinder.h”
Cylinder::Cylinder(std::string vert, std::string frag, std::string texName) :Object(vert, frag, texName)
{
}
Cylinder::~Cylinder()
{
}
void Cylinder::initData(DataParam *param)
{
dataParam = *param;
GLfloat radius = dataParam.radius;
GLuint longSegments = dataParam.longSegments;
GLfloat height = dataParam.height;
float fTheta = (glm::pi<float>() * 2.0f) / longSegments; //经度上角度差:Theta //生成顶点数据 verticesSize =2 * (longSegments + 1) + (longSegments + 2) + (longSegments + 2); //计算顶点数量 vertices = new TextureColorVertex[verticesSize]; //创建顶点数组 verticesSize *= sizeof(TextureColorVertex); TextureColorVertex * p = vertices; //生成侧面顶点数据,请补充代码 for (int i = 0; i < (longSegments + 1); i++) { float theta = i * fTheta; float x = radius * cos(theta); float z = radius * sin(theta); // 底部顶点 (y = -height/2) p->coordinate.x = x; p->coordinate.y = -height / 2.0f; p->coordinate.z = z; p->texture.s = static_cast<float>(i) / longSegments; // s: 0→1 p->texture.t = 0.0f; p->color.r = 1.0f; p->color.g = 1.0f; p->color.b = 1.0f; ++p; // 顶部顶点 (y = +height/2) p->coordinate.x = x; p->coordinate.y = height / 2.0f; p->coordinate.z = z; p->texture.s = static_cast<float>(i) / longSegments; p->texture.t = 1.0f; p->color.r = 1.0f; p->color.g = 1.0f; p->color.b = 1.0f; ++p; } int start = 2 * (longSegments + 1); //生成上底顶点数据,请补充代码 vertices[start].coordinate.x = 0.0f; vertices[start].coordinate.y = height/2.0f; vertices[start].coordinate.z = 0.0f; vertices[start].texture.s =0.5f; vertices[start].texture.t =0.5f; vertices[start].color.r =1.0f; vertices[start].color.g =1.0f; vertices[start].color.b =1.0f; ++start; for (int i = 0; i < longSegments + 1; i++) { float theta = i * fTheta; float x = radius * cos(theta); float z = radius * sin(theta); vertices[i + start].coordinate.x =x; vertices[i + start].coordinate.y =height/2.0f; vertices[i + start].coordinate.z =z; vertices[i + start].texture.s =0.5f+0.5f*cos(theta); vertices[i + start].texture.t =0.5f-0.5f*sin(theta); vertices[i + start].color.r =1.0f; vertices[i + start].color.g =1.0f; vertices[i + start].color.b =1.0f; } start += longSegments + 1; //生成下底顶点数据,请补充代码 vertices[start].coordinate.x =0.0f; vertices[start].coordinate.y =-height/2.0f; vertices[start].coordinate.z =0.0f; vertices[start].texture.s = 0.5f; vertices[start].texture.t = 0.5f; vertices[start].color.r = 1.0f; vertices[start].color.g = 1.0f; vertices[start].color.b = 1.0f; ++start; for (int i = 0; i < longSegments + 1; i++) { float theta = i * fTheta; float x = radius * cos(theta); float z = radius * sin(theta); vertices[i + start].coordinate.x = x; vertices[i + start].coordinate.y = -height / 2.0f; vertices[i + start].coordinate.z = z; vertices[i + start].texture.s = 0.5f + 0.5f * cos(theta); vertices[i + start].texture.t = 0.5f - 0.5f * sin(theta); vertices[i + start].color.r = 1.0f; vertices[i].color.g = 1.0f; vertices[i].color.b = 1.0f; } createBuffer(sizeof(TextureColorVertex)); delete[]vertices; revolutionAngle = 0.0f; //公转角度(用于动画) rotationAngle = 0.0f; //自转角度(用于绕自身旋转) revolutionSpeed = 5.0f; //公转角速度(度/秒) rotationSpeed = 1.0f; //自转角速度(度/秒)
}
void Cylinder::renderObject()
{
glBindVertexArray(VAO);
GLint first = 0;
glDrawArrays(GL_TRIANGLE_STRIP, first, (dataParam.longSegments + 1) * 2);
first += (dataParam.longSegments + 1) * 2;
glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments +2);
first += dataParam.longSegments + 2;
glDrawArrays(GL_TRIANGLE_FAN,first, dataParam.longSegments + 2);
}
void Cylinder::update(float dt)
{
revolutionAngle += revolutionSpeed * dt;
rotationAngle += rotationSpeed * dt * 3;
model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::translate(model, glm::vec3(0.0f, 0.0f,3.0f));
model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 0.0f,1.0f));
//model = glm::rotate(model, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
}#pragma once
#include “Object.h”
class Cylinder :public Object
{
public:
Cylinder(std::string vert, std::string frag, std::string texName = “”);
~Cylinder();
void initData(DataParam *param = nullptr); void renderObject(); void update(float dt);
private:
DataParam dataParam;
};
#include “Demo.h”
Demo::Demo()
{
cullMode = GL_BACK;
frontFace = GL_CCW;
enableCullFace = false;
}
Demo::~Demo()
{
}
void Demo::setRenderParameter(bool enableCullFace, GLenum cullMode, GLenum frontFace)
{
this->enableCullFace = enableCullFace;
this->cullMode = cullMode;
this->frontFace = frontFace;
}
void Demo::beginRender()
{
if (enableCullFace)
{
glEnable(GL_CULL_FACE);
}
else
{
glDisable(GL_CULL_FACE);
}
glCullFace(cullMode);
glFrontFace(frontFace);
}#ifndef DEMO_H_
#define DEMO_H_
#include <glad/glad.h>
class Demo
{
public:
Demo();
~Demo();
private:
bool enableCullFace;
GLenum cullMode;
GLenum frontFace;
protected:
const char* vertexShaderSource;
const char* fragmentShaderSource;
public:
virtual void setRenderParameter(bool enableCullFace = false, GLenum cullMode = GL_FRONT, GLenum frontFace = GL_CCW);
virtual void beginRender();
virtual void render() = 0;
virtual void update(float deltaTime) = 0;
};
#endif
#include “Demo08.h”
#include “TexturePool.h”
Demo08::Demo08(int scr_width, int scr_height)
{
screen_height = scr_height;
screen_width = scr_width;
}
Demo08::~Demo08()
{
cleanUp();
}
void Demo08::init()
{
TexturePool* textPool = TexturePool::getInstance();
TexturePool::getInstance()->addTexture("sun", "./texture/sun.jpg"); TexturePool::getInstance()->addTexture("earth", "./texture/earth.jpg"); TexturePool::getInstance()->addTexture("cube", "./texture/container.jpg"); TexturePool::getInstance()->addTexture("saturn", "./texture/saturn.jpg"); objects[0] = new Cube18("star.vert", "star.frag", "cube"); //定义立方体对象 objects[1] = new Sphere("star.vert", "star.frag", "earth"); //定义球对象 objects[2] = new Cylinder("star.vert", "star.frag", "sun"); //定义圆柱对象 objects[3] = new Cone("star.vert", "star.frag", "saturn"); //定义圆锥对象 objects[0]->initData(); DataParam earthParam = { 20,20,1.0f }; objects[1]->initData(&earthParam); DataParam cylinderParam = { 20,20,1.0f,4.0f }; objects[2]->initData(&cylinderParam); DataParam coneParam = { 10,10,1.0f,2.0f }; objects[3]->initData(&coneParam);
}
void Demo08::cleanUp()
{
if (earth)
{
delete earth;
}
if (cube)
{
delete cube;
}
if (cylinder)
{
delete cylinder;
}
if (cone) { delete cone; } for (int i = 0; i < 4; ++i) { if (objects[i]) { delete objects[i]; } }
}
void Demo08::update(float dt) //更新所有可动画对象的状态(如旋转、公转)
{
for (int i = 0; i < 4; ++i)
{
objects[i]->update(dt); //调用每个对象的 update 方法更新其模型矩阵
}
}
void Demo08::render()
{
glClearColor(0.2, 0.3, 0.2, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
beginRender();
glEnable(GL_DEPTH_TEST);
// create transformations glm::mat4 view = glm::mat4(1.0f); glm::mat4 projection = glm::mat4(1.0f); view = glm::translate(view, glm::vec3(0.0f, 0.0f, -12.0f)); if (screen_height <= 0 || screen_width <= 0) { return; } // 设置透视投影:45度视野,宽高比,近远裁剪平面 projection = glm::perspective(glm::radians(45.0f), (float)screen_width / (float)screen_height, 0.1f, 100.0f); for (int i = 0; i < 4; ++i) { objects[i]->render(view, projection); }
}
void Demo08::setViewport(int width, int height)
{
screen_width = width;
screen_height = height;
}#pragma once
#include “Demo.h”
#include “Cube18.h”
#include “Sphere.h”
#include “Cylinder.h”
#include “Cone.h”
class Demo08 : public Demo
{
public:
Demo08(int scr_width,int scr_height);
~Demo08();
private:
Cube18* cube;
Sphere* earth;
Cylinder* cylinder;
Cone* cone;
Object* objects[4]; int screen_width; int screen_height;
public:
void render();
void update(float deltaTime);
void init();
void cleanUp();
void setViewport(int width, int height);
};
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include
#include “Demo08.h”
unsigned int scr_width = 1200;
unsigned int scr_height = 800;
GLFWwindow* window;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void processInput(GLFWwindow* window);
void update(float dt);
void render();
void init();
void cleanup();
bool enableCullFace = true;
GLenum cullMode = GL_BACK;
GLenum frontFace = GL_CCW;
Demo08* demo08 = nullptr;
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
window = glfwCreateWindow(scr_width, scr_height, "Lab3-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); glfwSetKeyCallback(window, key_callback); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } int nrAttributes; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes); std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl; init(); double t = 0.5; while (!glfwWindowShouldClose(window)) { processInput(window); double dt = glfwGetTime() - t; t = glfwGetTime(); update(dt); render(); glfwSwapBuffers(window); glfwPollEvents(); } cleanup(); glfwTerminate(); return 0;
}
void cleanup()
{
if (demo08)
{
delete demo08;
}
}
void init()
{
demo08 = new Demo08(scr_width, scr_height);
demo08->setRenderParameter(enableCullFace, cullMode, frontFace);
demo08->init();
}
void update(float dt)
{
if (demo08)
{
demo08->update((float)dt);
}
}
void render()
{
if (demo08)
{
demo08->render();
}
}
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)
{
scr_width = width;
scr_height = height;
glViewport(0, 0, width, height);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
// 判断按键是否被释放
if (action == GLFW_RELEASE)
{
}
}#include <glad/glad.h>
#include “TexturePool.h”
#include “Object.h”
Object::Object(std::string vert, std::string frag, std::string texName)
{
createShader(vert.c_str(), frag.c_str());
if (texName != “”)
{
texture = TexturePool::getInstance()->getTexture(texName);
// activate shader
shader->use();
shader->setInt("tex", 0); shader->setVec4("testColor", glm::vec4(255, 0, 0, 255)); } vertices = nullptr; indices = nullptr; stride = 0;
}
Object::~Object()
{
glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); if (shader) { delete shader; } /*if (vertices) { delete[]vertices; }*/
}
void Object::createShader(const char* vert, const char* frag)
{
if (shader)
{
delete shader;
}
shader = new Shader(vert, frag);
}
void Object::setTexture(std::string texName)
{
texture = TexturePool::getInstance()->getTexture(texName);
}
void Object::createBuffer(GLsizei stride, bool createEBO , GLenum ussage)
{
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
if (createEBO)
{
glGenBuffers(1, &EBO);
}
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, verticesSize, vertices, ussage); if (createEBO) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, ussage); } this -> stride = stride; updateDataBuffer();
}
void Object::render(glm::mat4& view, glm::mat4& projection)
{
glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(VAO); shader->use(); shader->setMat4("model", model); shader->setMat4("view", view); shader->setMat4("projection", projection); renderObject();
}
void Object::updateDataBuffer()
{
//position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(1 * sizeof(glm::vec3))); glEnableVertexAttribArray(1); // texture coord attribute glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(2 * sizeof(glm::vec3))); glEnableVertexAttribArray(2);
}#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include
#include <glad/glad.h> // 必须包含,提供 GLuint, GLenum 等定义
#include “Shader.h”
typedef struct
{
glm::vec3 coordinate;
glm::vec3 color;
glm::vec2 texture;
} TextureColorVertex;
typedef struct
{
GLuint latSegments;
GLuint longSegments;
GLfloat radius;
GLfloat height;
}DataParam;
class Object
{
public:
Object(std::string vert, std::string frag, std::string texName = “”);
virtual ~Object();
protected:
Shader* shader;
TextureColorVertex* vertices; GLushort * indices; GLuint indexCount; GLint verticesSize; GLuint indexSize; GLuint texture; GLuint VBO, VAO, EBO;
protected:
glm::mat4 model;
float rotationSpeed;
float revolutionSpeed;
float rotationAngle;
float revolutionAngle;
glm::vec3 translation;
GLsizei stride; void createBuffer(GLsizei stride,bool createEBO = false, GLenum ussage = GL_STATIC_DRAW);
public:
void createShader(const char* vert, const char* frag);
virtual void initData(DataParam *param = nullptr) = 0;
void setTexture(std::string texName);
void render(glm::mat4& view, glm::mat4& projection);
virtual void update(float dt) {}
virtual void renderObject() = 0;
virtual void updateDataBuffer();
};
#pragma once
//#ifndef SHADER_H
//#define SHADER_H
#include <glad/glad.h>
#include <glm/glm.hpp>
#include
#include
#include
#include
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#include “Sphere.h”
#include
// 定义 PI,兼容无 M_PI 的环境
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_PI_2
#define M_PI_2 (M_PI / 2.0f)
#endif
Sphere::Sphere(std::string vert, std::string frag, std::string texName) :Object(vert, frag,texName )
{
}
Sphere::~Sphere()
{
}
void Sphere::initData(DataParam *param)
{
GLfloat radius = param->radius; GLuint longSegments = param->longSegments; GLuint latSegments = param->latSegments; float fPhi = M_PI / latSegments; //纬度上角度差:Phi float fTheta =2.0f * M_PI / longSegments; //经度上角度差:Theta //生成顶点数据,请补充代码 verticesSize =(longSegments + 1) * (latSegments + 1); vertices = new TextureColorVertex[(longSegments + 1) * (latSegments + 1)]; //创建顶点数组 TextureColorVertex * p = vertices; for (GLuint i = 0; i < latSegments + 1; i++) { float phi = i * fPhi; // 极角 φ ∈ [0, π] float sinPhi = std::sin(phi); float cosPhi = std::cos(phi); float latitude = phi - M_PI_2; //纬度 for (GLuint j = 0; j < longSegments + 1; j++) { float theta = j * fTheta; // 方位角 θ ∈ [0, 2π] float longitude =theta; //经度 p->coordinate.x = radius * sinPhi * std::cos(theta); p->coordinate.y = radius * cosPhi; p->coordinate.z = radius * sinPhi * std::sin(theta); p->color.r = 1.0f; p->color.g = 1.0f; p->color.b = 1.0f; p->texture.s = static_cast<float>(j) / longSegments; // u 坐标 [0,1] p->texture.t = 1.0f - static_cast<float>(i) / latSegments; // v 坐标 [0,1],翻转以匹配纹理顶部对齐 p++; } } //生成索引数据 indexCount = indexCount = (latSegments) * (2 * (longSegments + 1) + 2); //计算索引数量 indices = new GLushort[indexCount]; indexSize = indexCount * sizeof(GLushort); GLushort * pIdx = indices; for (GLuint i = 0; i < latSegments + 1; i++) { GLuint top_offset = i * (longSegments + 1); GLuint bottom_offset = (i + 1) * (longSegments + 1); // 插入退化三角形(开始) if (i > 0) { *pIdx++ = top_offset; *pIdx++ = top_offset; } for (GLuint j = 0; j < longSegments + 1; j++) { *pIdx++ = bottom_offset + j; // 下一行(南) *pIdx++ = top_offset + j; // 上一行(北) } *pIdx++ = bottom_offset + longSegments; *pIdx++ = bottom_offset + longSegments; } createBuffer(sizeof(TextureColorVertex),true); delete[]vertices; delete[]indices; revolutionAngle = 0.0f; //当前公转角度(绕中心Y轴旋转) rotationAngle = 0.0f; //当前自转角度(绕自身Y轴旋转) revolutionSpeed = 0.01f; //公转角速度(每帧增加的角度值) rotationSpeed = 0.5f; //自转角速度(每帧增加的角度值)
}
void Sphere::renderObject()
{
glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, 0);
}
void Sphere::update(float dt)
{
revolutionAngle += revolutionSpeed;
rotationAngle += rotationSpeed;
model = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::translate(model, glm::vec3(5.0f,0.0f,0.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
}
#pragma once
#include “Object.h”
class Sphere : public Object
{
public:
Sphere(std::string vert, std::string frag, std::string texName = “”);
~Sphere();
void initData(DataParam *param = nullptr);
void renderObject();
void update(float dt);
};
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D tex;
void main()
{
FragColor = texture(tex, TexCoord);
}#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTextCoord;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec4 testColor;
out vec4 color;
void main()
{
gl_Position = projection * view * model * vec4(aPos,1.0f);
TexCoord = vec2(aTextCoord.x,1-aTextCoord.y);
color = testColor;
}#include “TexturePool.h”
#include <SOIL2/SOIL2.h>
#include
TexturePool::TexturePool()
{
}
TexturePool::~TexturePool()
{
for (Textures::iterator ite = textures.begin(); ite != textures.end(); ++ite)
{
glDeleteTextures(1, &ite->second);
}
}
void TexturePool::addTexture(string name, string path)
{
GLuint texID;
if (name.empty())
{
return;
}
texID = SOIL_load_OGL_texture(path.c_str(), 0, 0, SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y); if (texID != 0) { textures[name] = texID; } else { std::cout << "Failed to load texture" << path <<" " <<std::endl; } glBindTexture(GL_TEXTURE_2D, texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
TexturePool* TexturePool::getInstance()
{
static TexturePool instance;
return &instance;
}
GLuint TexturePool::getTexture(string name)
{
if (textures.find(name) != textures.end()) { return textures[name]; } return 0;
}#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include
#include
using namespace std;
typedef map<string, GLuint> Textures;
class TexturePool
{
public:
virtual ~TexturePool();
private:
TexturePool();
Textures textures;
public:
void addTexture(string name, string path);
static TexturePool *getInstance();
GLuint getTexture(string name);
};
glad.c和glad.h也放了已在 Demo08.exe 中执行断点指令(__debugbreak()语句或类似调用)。