Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // g++ rgb_cell.cpp opengl/glad.c -o rgb_cell -lglfw -ldl -lGL -I./include
- #include <glad/glad.h>
- #include <GLFW/glfw3.h>
- #include <iostream>
- #include <vector>
- #include <map>
- #include <cstring> // For memset
- #include <algorithm> // For min and max
- #include <string> // For std::to_string
- // Define window and texture dimensions
- const int WINDOW_WIDTH = 1920;
- const int WINDOW_HEIGHT = 1080;
- // Define cell size for dividing the texture
- const int GRID_CELL_SIZE = 128;
- // Define a patch structure
- struct RGBPatch {
- int x_offset; // X position of the patch in the texture
- int y_offset; // Y position of the patch in the texture
- int width; // Width of the patch
- int height; // Height of the patch
- std::vector<unsigned char> data; // RGB data for the patch
- };
- // Vertex Shader Source
- const char* vertexShaderSource = R"(
- #version 330 core
- layout(location = 0) in vec2 aPos;
- layout(location = 1) in vec2 aTexCoord;
- out vec2 TexCoord;
- void main() {
- gl_Position = vec4(aPos, 0.0, 1.0);
- TexCoord = aTexCoord;
- }
- )";
- // Fragment Shader Source
- const char* fragmentShaderSource = R"(
- #version 330 core
- out vec4 FragColor;
- in vec2 TexCoord;
- uniform sampler2D texture1;
- void main() {
- FragColor = texture(texture1, TexCoord);
- }
- )";
- // Create some patches
- void createPatches(std::vector<RGBPatch>& patches, int numPatches, int textureWidth, int textureHeight) {
- for (int i = 0; i < numPatches; ++i) {
- RGBPatch patch;
- patch.width = 10 + (i % 20); // Width between 10 and 30
- patch.height = 10 + ((i + 5) % 15); // Height between 10 and 25
- patch.x_offset = (i * 23) % (textureWidth - patch.width);
- patch.y_offset = (i * 37) % (textureHeight - patch.height);
- // Generate RGB data for the patch
- patch.data.resize(patch.width * patch.height * 3);
- std::fill(patch.data.begin(), patch.data.end(), static_cast<unsigned char>((i * 5) % 256)); // Fill with a color
- patches.push_back(patch);
- }
- }
- // Group patches into grid cells
- void groupPatchesIntoCells(std::map<std::pair<int, int>, std::vector<RGBPatch>>& gridCells,
- const std::vector<RGBPatch>& patches) {
- for (const auto& patch : patches) {
- // Calculate which cells this patch belongs to
- int startCellX = patch.x_offset / GRID_CELL_SIZE;
- int startCellY = patch.y_offset / GRID_CELL_SIZE;
- int endCellX = (patch.x_offset + patch.width - 1) / GRID_CELL_SIZE;
- int endCellY = (patch.y_offset + patch.height - 1) / GRID_CELL_SIZE;
- // Add the patch to all overlapping cells
- for (int cellY = startCellY; cellY <= endCellY; ++cellY) {
- for (int cellX = startCellX; cellX <= endCellX; ++cellX) {
- gridCells[{cellX, cellY}].push_back(patch);
- }
- }
- }
- }
- // Compile a shader
- GLuint compileShader(GLenum shaderType, const char* source) {
- GLuint shader = glCreateShader(shaderType);
- glShaderSource(shader, 1, &source, nullptr);
- glCompileShader(shader);
- // Check for compilation errors
- int success;
- char infoLog[512];
- glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
- if (!success) {
- glGetShaderInfoLog(shader, 512, nullptr, infoLog);
- std::cerr << "ERROR: Shader Compilation Failed\n" << infoLog << std::endl;
- }
- return shader;
- }
- // Link shaders into a program
- GLuint createShaderProgram(const char* vertexSource, const char* fragmentSource) {
- GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexSource);
- GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSource);
- GLuint program = glCreateProgram();
- glAttachShader(program, vertexShader);
- glAttachShader(program, fragmentShader);
- glLinkProgram(program);
- // Check for linking errors
- int success;
- char infoLog[512];
- glGetProgramiv(program, GL_LINK_STATUS, &success);
- if (!success) {
- glGetProgramInfoLog(program, 512, nullptr, infoLog);
- std::cerr << "ERROR: Shader Linking Failed\n" << infoLog << std::endl;
- }
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- return program;
- }
- int main() {
- if (!glfwInit()) {
- std::cerr << "Failed to initialize GLFW" << std::endl;
- return -1;
- }
- GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Cell-Based Texture Updates", nullptr, nullptr);
- if (!window) {
- std::cerr << "Failed to create GLFW window" << std::endl;
- glfwTerminate();
- return -1;
- }
- glfwMakeContextCurrent(window);
- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
- std::cerr << "Failed to initialize GLAD" << std::endl;
- return -1;
- }
- // Create a shader program
- GLuint shaderProgram = createShaderProgram(vertexShaderSource, fragmentShaderSource);
- // Define fullscreen quad vertices and texture coordinates
- float quadVertices[] = {
- // Positions // Texture Coords
- -1.0f, -1.0f, 0.0f, 0.0f, // Bottom-left
- 1.0f, -1.0f, 1.0f, 0.0f, // Bottom-right
- -1.0f, 1.0f, 0.0f, 1.0f, // Top-left
- 1.0f, 1.0f, 1.0f, 1.0f // Top-right
- };
- // Create VAO and VBO
- GLuint VAO, VBO;
- glGenVertexArrays(1, &VAO);
- glGenBuffers(1, &VBO);
- glBindVertexArray(VAO);
- glBindBuffer(GL_ARRAY_BUFFER, VBO);
- glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
- // Position attribute
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
- glEnableVertexAttribArray(0);
- // Texture coordinate attribute
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
- glEnableVertexAttribArray(1);
- // Create a texture
- GLuint texture;
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- // Generate patches
- std::vector<RGBPatch> patches;
- createPatches(patches, 1000, WINDOW_WIDTH, WINDOW_HEIGHT);
- // FPS calculation variables
- double previousTime = glfwGetTime();
- int frameCount = 0;
- // Main render loop
- unsigned char colorValue = 0;
- while (!glfwWindowShouldClose(window)) {
- // Increment the color value for dynamic updates
- colorValue = (colorValue + 1) % 256;
- // Update patch colors dynamically
- for (auto& patch : patches) {
- std::fill(patch.data.begin(), patch.data.end(), colorValue);
- }
- // Group patches into grid cells
- std::map<std::pair<int, int>, std::vector<RGBPatch>> gridCells;
- groupPatchesIntoCells(gridCells, patches);
- // Update each cell
- for (const auto& [cell, cellPatches] : gridCells) {
- // Calculate the bounding box for this cell
- int minX = cell.first * GRID_CELL_SIZE;
- int minY = cell.second * GRID_CELL_SIZE;
- int maxX = minX + GRID_CELL_SIZE;
- int maxY = minY + GRID_CELL_SIZE;
- // Adjust the bounding box based on the patches in this cell
- for (const auto& patch : cellPatches) {
- minX = std::min(minX, patch.x_offset);
- minY = std::min(minY, patch.y_offset);
- maxX = std::max(maxX, patch.x_offset + patch.width);
- maxY = std::max(maxY, patch.y_offset + patch.height);
- }
- int updateWidth = maxX - minX;
- int updateHeight = maxY - minY;
- // Allocate a buffer for the cell's affected region
- std::vector<unsigned char> cellBuffer(updateWidth * updateHeight * 3, 0);
- // Fill the buffer with patch data
- for (const auto& patch : cellPatches) {
- for (int y = 0; y < patch.height; ++y) {
- for (int x = 0; x < patch.width; ++x) {
- int patchIndex = (y * patch.width + x) * 3;
- int cellIndex = ((patch.y_offset - minY + y) * updateWidth + (patch.x_offset - minX + x)) * 3;
- cellBuffer[cellIndex + 0] = patch.data[patchIndex + 0]; // Red
- cellBuffer[cellIndex + 1] = patch.data[patchIndex + 1]; // Green
- cellBuffer[cellIndex + 2] = patch.data[patchIndex + 2]; // Blue
- }
- }
- }
- // Update the texture for this cell
- glTexSubImage2D(GL_TEXTURE_2D, 0, minX, minY, updateWidth, updateHeight, GL_RGB, GL_UNSIGNED_BYTE, cellBuffer.data());
- }
- // Render the texture
- glClear(GL_COLOR_BUFFER_BIT);
- glUseProgram(shaderProgram);
- glBindVertexArray(VAO);
- glBindTexture(GL_TEXTURE_2D, texture);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- // Calculate FPS
- double currentTime = glfwGetTime();
- frameCount++;
- if (currentTime - previousTime >= 1.0) {
- int fps = frameCount;
- frameCount = 0;
- previousTime = currentTime;
- // Update window title with FPS
- std::string title = "Cell-Based Texture Updates - FPS: " + std::to_string(fps);
- glfwSetWindowTitle(window, title.c_str());
- }
- // Swap buffers and poll events
- glfwSwapBuffers(window);
- glfwPollEvents();
- }
- // Cleanup
- glDeleteBuffers(1, &VBO);
- glDeleteVertexArrays(1, &VAO);
- glDeleteTextures(1, &texture);
- glDeleteProgram(shaderProgram);
- glfwTerminate();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement