0
$\begingroup$

I am trying to do a probabilistic simulation on a 20X20 grid. The simulation will generate numbers say 2, 3 or 4 and grid location say [5][4]. I will convert the simulated number to c string and add ".png" to feed to stb as the name of image file to load as a texture at a certain block. I have been able to create the grid. Here is the code-

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb/stb_image.h>
#include <iostream>

const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";

const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(0.8f, 0.3f, 0.02f, 1.0f);\n"
"}\n\0";

const GLint CELL_NO = 400; // total number of cells
const GLfloat CELL_DIM = 0.075f; // length and width of each cell
const GLfloat CELL_GAP = 0.025f; // Gap between cells

struct point {
    GLfloat x = 0.0f;
    GLfloat y = 0.0f;
    GLfloat z = 0.0f;
};

typedef struct block {
    point vertices[4];
}cell;

GLfloat vertice[400][12] = { 0.0f };
GLuint indices[] = {
    0,  1,  2,
    2,  3,  0
};

// cell vertex data
void inititialize(cell* C)
{
    // corner left top
    C[0].vertices[0] = { -0.9875f, 0.9875f };
    C[0].vertices[1] = { -0.9875f, 0.9125f };
    C[0].vertices[2] = { -0.9125f, 0.9125f };
    C[0].vertices[3] = { -0.9125f, 0.9875f };

    // corner bottom left
    C[380].vertices[0] = { -0.9875f, -0.9125f };
    C[380].vertices[1] = { -0.9875f, -0.9875f };
    C[380].vertices[2] = { -0.975f, -0.9875f };
    C[380].vertices[3] = { -0.975f, -0.9125f };


    // left column
    for (int i = 1; i < 20; i++)
    {
        for (short k = 0; k < 4; k++)
        {
            C[i * 20].vertices[k] = { C[(i - 1) * 20].vertices[k].x, C[(i - 1) * 20].vertices[k].y - CELL_DIM - CELL_GAP };
        }
    }

    // whole grid
    for (int i = 0; i < 20; i++)
    {
        for (int j = 1; j < 20; j++)
        {
            for (short k = 0; k < 4; k++)
            {
                C[i * 20 + j].vertices[k] = { C[i * 20 + j - 1].vertices[k].x + CELL_DIM + CELL_GAP, C[i * 20 + j - 1].vertices[k].y };
            }
        }
    }
}

// loading the vertex data to vertice so opengl can read the data
void load_vertices(cell* c)
{
    for (unsigned int i = 0; i < 20; i++)
    {
        for (unsigned int j = 0; j < 20; j++)
        {
            vertice[i * 20 + j][0] = c[i * 20 + j].vertices[0].x;
            vertice[i * 20 + j][1] = c[i * 20 + j].vertices[0].y;
            vertice[i * 20 + j][2] = c[i * 20 + j].vertices[0].z;
            vertice[i * 20 + j][3] = c[i * 20 + j].vertices[1].x;
            vertice[i * 20 + j][4] = c[i * 20 + j].vertices[1].y;
            vertice[i * 20 + j][5] = c[i * 20 + j].vertices[1].z;
            vertice[i * 20 + j][6] = c[i * 20 + j].vertices[2].x;
            vertice[i * 20 + j][7] = c[i * 20 + j].vertices[2].y;
            vertice[i * 20 + j][8] = c[i * 20 + j].vertices[2].z;
            vertice[i * 20 + j][9] = c[i * 20 + j].vertices[3].x;
            vertice[i * 20 + j][10] = c[i * 20 + j].vertices[3].y;
            vertice[i * 20 + j][11] = c[i * 20 + j].vertices[3].z;
        }
    }
}



void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}

void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    GLFWwindow* window = glfwCreateWindow(800, 800, "Boltzman_distribution", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Window not Created" << std::endl;
        glfwDestroyWindow(window);
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    glViewport(0, 0, 800, 800);
    
    
    cell* c = new cell[400];
    inititialize(c);
    load_vertices(c);
    delete []c;



    GLuint vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "VERTEX SHADER ERROR" << std::endl;
    }
    

    GLuint fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "FRAGMENT SHADER ERROR" << std::endl;
    }
    GLuint shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "SHADER PROGRAM ERROR" << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    
    
    GLuint VBO[400] = { 0 }, VAO[400] = { 0 }, EBO = { 0 };
    
    glGenVertexArrays(400, VAO);
    glGenBuffers(400, &VBO[0]);
    glGenBuffers(1, &EBO);

    for (us i = 0; i < 400; i++)
    {
        glBindVertexArray(VAO[i]);
        glBindBuffer(GL_ARRAY_BUFFER, VBO[i]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertice[i]), vertice[i], 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, 3 * sizeof(GLfloat), (void*)0); // Vertex attributes stay the same
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }


    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    while (!glfwWindowShouldClose(window))
    {
        processInput(window);

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        
        glUseProgram(shaderProgram);

        for (us i = 0; i < 400; i++)
        {
            glBindVertexArray(VAO[i]);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
            glBindVertexArray(0);
        }
        
        glfwSwapBuffers(window);
        glfwPollEvents();
    }


    glDeleteVertexArrays(400, VAO);
    glDeleteBuffers(400, VBO);
    glDeleteProgram(shaderProgram);


    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

To load the texture, I will have to change the vertice array GLfloat vertice[400][20] = { 0.0f }; (colors are not important).

void load_vertices(cell* c)
    {
        for (unsigned int i = 0; i < 20; i++)
        {
            for (unsigned int j = 0; j < 20; j++)
            {
                vertice[i * 20 + j][0] = c[i * 20 + j].vertices[0].x;
                vertice[i * 20 + j][1] = c[i * 20 + j].vertices[0].y;
                vertice[i * 20 + j][2] = c[i * 20 + j].vertices[0].z;
                vertice[i * 20 + j][3] = 0.0f;
                vertice[i * 20 + j][4] = 1.0f;

                vertice[i * 20 + j][5] = c[i * 20 + j].vertices[1].x;
                vertice[i * 20 + j][6] = c[i * 20 + j].vertices[1].y;
                vertice[i * 20 + j][7] = c[i * 20 + j].vertices[1].z;
                vertice[i * 20 + j][8] = 0.0f;
                vertice[i * 20 + j][9] = 0.0f;

                vertice[i * 20 + j][10] = c[i * 20 + j].vertices[2].x;
                vertice[i * 20 + j][11] = c[i * 20 + j].vertices[2].y;
                vertice[i * 20 + j][12] = c[i * 20 + j].vertices[2].z;
                vertice[i * 20 + j][13] = 1.0f;
                vertice[i * 20 + j][14] = 0.0f;

                vertice[i * 20 + j][15] = c[i * 20 + j].vertices[3].x;
                vertice[i * 20 + j][16] = c[i * 20 + j].vertices[3].y;
                vertice[i * 20 + j][17] = c[i * 20 + j].vertices[3].z;
                vertice[i * 20 + j][18] = 1.0f;
                vertice[i * 20 + j][19] = 1.0f;
            }
        }
    }

vertex shader will become-

const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTex;\n"
"out vec3 color;\n"
"out vec2 texCoord;\n"
"void main()\n"
"{\n"
 "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
 "   texCoord = aTex;\n"
"}\n\0"

and I can't figure out what fragment shader should be?

Also for texture i will have to generate 3 texture buffer for and specify which texture to load in which block and how to render the whole thing?

I need an example code where say 51th, 100th, 205th block has values 2, 3, 4 respectively and changes to 3, 2, 4 respectively and changes back and forth.

My grid is 20X20. so vertice[50], vertice[99], vertice[204] has the vertex data.

I have searched a lot and found a lot of tutorial for making games in c++ but almost none for scientific visualization.

$\endgroup$
1
  • $\begingroup$ Simplest way to do this would be to pack the 3 (or however many) images into a single texture (an atlas), and have your code generate texture coordinates for each square to select the appropriate sub-image within the atlas. $\endgroup$ Sep 3, 2022 at 22:12

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.