-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrenderer.h
101 lines (78 loc) · 3.35 KB
/
renderer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#ifndef RENDERER_H
#define RENDERER_H
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "shader.h"
#include "model.h"
#include <stb_image_write.h>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <iomanip>
class Renderer {
private:
Shader& shader;
Model& model;
GLuint FBO;
unsigned int RENDER_SIZE_X;
unsigned int RENDER_SIZE_Y;
public:
Renderer(Shader& shader, Model& model, GLuint FBO, std::string filename, unsigned int RENDER_SIZE_X, unsigned int RENDER_SIZE_Y)
: shader(shader), model(model), FBO(FBO), RENDER_SIZE_X(RENDER_SIZE_X), RENDER_SIZE_Y(RENDER_SIZE_Y) {}
void renderSpin(const int numFrames, const std::string filename) {
// Find the position of the last dot in the filename
size_t dotPos = filename.find_last_of(".");
// Split the filename into the name and extension
std::string name = filename.substr(0, dotPos);
std::string extension = filename.substr(dotPos);
// Calculate the rotation angle for each frame
float rotationAngle = 360.0f / numFrames;
for (int i = 0; i < numFrames; i++) {
// Create a new stringstream
std::stringstream ss;
// Add the name, a four-digit counter, and the extension to the stringstream
ss << name << std::setfill('0') << std::setw(4) << i << extension;
// Get the new filename from the stringstream
std::string newFilename = ss.str();
// Rotate the model
glm::mat4 scene = glm::mat4(1.0f);
scene = glm::rotate(scene, glm::radians(i * rotationAngle), glm::vec3(0.0f, 1.0f, 0.0f));
// Render commands
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glViewport(0, 0, RENDER_SIZE_X, RENDER_SIZE_Y);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
shader.use();
// Send transforms to shader
int modelLoc = glGetUniformLocation(shader.ID, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(scene));
model.Draw(shader);
// Call the writeFrame function with the new filename
writeFrame(newFilename);
}
}
void writeFrame(const std::string& filename) {
// Print filename to console
std::cout << "Writing frame: " << filename.c_str() << std::endl;
// Create array to hold pixel data
unsigned char* pixels = new unsigned char[RENDER_SIZE_X*RENDER_SIZE_Y*4]; // 4 channels for RGBA
// Bind FBO and read to array
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glReadPixels(0, 0, RENDER_SIZE_X, RENDER_SIZE_Y, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Calculate scanline size
int scanlinesize = RENDER_SIZE_X*4*sizeof(char);
// Write to file using stb_image_write and check for errors
stbi_flip_vertically_on_write(true);
int result = stbi_write_png(filename.c_str(), RENDER_SIZE_X, RENDER_SIZE_Y, 4, pixels, scanlinesize);
if (!result) {
std::cerr << "Error: Failed to write frame to " << filename.c_str() << std::endl;
}
delete[] pixels;
}
};
#endif