cpp-cheat
cpp-cheat copied to clipboard
Cpp
:partying_face: :partying_face: :partying_face:
Ciro Santilli, it is code that I tried to port code C to C++
#include <iostream>
#include <SDL.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GLFW\glfw3.h>
#include <math.h>
#include <time.h>
#pragma comment (lib, "glew32.lib")
#pragma comment (lib, "freeglut.lib")
using namespace std;
static const GLuint WINDOW_WIDTH = 512;
static const GLuint WIDTH = 256;
static const GLuint WORK_GROUP_WIDTH = 16;
static const GLfloat vertices_xy_uv[] = {
-1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 0.0, 0.0,
1.0, -1.0, 1.0, 0.0,
-1.0, -1.0, 1.0, 1.0,
};
static const GLuint indices[] = {
0, 1, 2,
0, 2, 3,
};
static unsigned int moving_boundary_value_swap = 1;
static GLfloat moving_boundary_value = 0.99;
static const GLchar* vertex_shader_source =
"#version 330 core\n"
"in vec2 coord2d;\n"
"in vec2 vertexUv;\n"
"out vec2 fragmentUv;\n"
"void main() {\n"
" gl_Position = vec4(coord2d, 0, 1);\n"
" fragmentUv = vertexUv;\n"
"}\n";
static const GLchar* fragment_shader_source =
"#version 330 core\n"
"in vec2 fragmentUv;\n"
"out vec3 color;\n"
"uniform sampler2D textureSampler;\n"
"void main() {\n"
" float r = texture(textureSampler, fragmentUv.yx).r;\n"
" color = vec3(r, r, r);\n"
"}\n";
static const char compute_shader_source_template[] =
"#version 430\n"
"layout (local_size_x = %d, local_size_y = %d) in;\n"
"layout (r32f, binding = 0) uniform image2D img_output;\n"
"layout (std430, binding=0) buffer temperatures {\n"
" float temperature[];\n"
"};\n"
"uniform uint width;\n"
"void main() {\n"
" ivec2 gid = ivec2(gl_GlobalInvocationID.xy);\n"
" ivec2 dims = imageSize(img_output);\n"
" uint i = gid.y * width + gid.x;\n"
" float t = temperature[i];\n"
" vec4 pixel = vec4(t, 0.0, 0.0, 1.0);\n"
" imageStore(img_output, gid, pixel);\n"
" temperature[i] = mod(t + 0.01, 1.0);\n"
"}\n";
/* The external boundary. */
void init_boundary(GLfloat* temperatures, size_t width, size_t height, int which, int time) {
const float PI2 = 2.0 * acos(-1.0);
const unsigned int sin_periods = 2;
switch (which) {
case 1:
/* Linear decrease.
*
* 1.0---0.5
* | |
* | |
* 0.5---0.0
* */
for (size_t i = 0; i < height; ++i) {
temperatures[i * width + 0] = 0.5 + (0.5 * (i / (float)height));
temperatures[i * width + width - 1] = 0.5 * (i / (float)height);
}
for (size_t j = 1; j < width - 1; ++j) {
temperatures[j] = 0.5 * (1.0 - (j / (float)width));
temperatures[(height - 1) * width + j] = 0.99 - (0.5 * (j / (float)width));
}
break;
case 2:
/* Sin, edges fixed
*
* 0.5---0.5
* | |
* | |
* 0.5---0.5
*
* Does N periods in the middle.
* */
for (size_t i = 0; i < height; ++i) {
float f = 0.5 * (0.99 + sin(sin_periods * PI2 * (i / (float)height)));
temperatures[i * width + 0] = f;
temperatures[i * width + width - 1] = f;
}
for (size_t j = 1; j < width - 1; ++j) {
float f = 0.5 * (0.99 + sin(sin_periods * PI2 * (j / (float)width)));
temperatures[j] = f;
temperatures[(height - 1) * width + j] = f;
}
break;
case 3:
/* Standing waves with time, edges fixed:
*
* 0.5---0.5
* | |
* | |
* 0.5---0.5
* */
for (size_t i = 0; i < height; ++i) {
float f = 0.5 * (0.99 + sin(PI2 * (sin_periods * i / (float)height)) * cos(time / 1000.0));
temperatures[i * width + 0] = f;
temperatures[i * width + width - 1] = f;
}
for (size_t j = 1; j < width - 1; ++j) {
float f = 0.5 * (0.99 + sin(PI2 * (sin_periods * j / (float)width)) * cos(time / 1000.0));
temperatures[j] = f;
temperatures[(height - 1) * width + j] = f;
}
break;
case 0:
default:
/*
* Const at 1.0.
*
* 1.0---1.0
* | |
* | |
* 1.0---1.0
* */
for (size_t i = 0; i < height; ++i) {
temperatures[i * width + 0] = 0.99;
temperatures[i * width + width - 1] = 0.99;
}
for (size_t j = 1; j < width - 1; ++j) {
temperatures[j] = 0.99;
temperatures[(height - 1) * width + j] = 0.99;
}
break;
}
}
/* An internal fixed boundary. We let derivatives be calculated on it for simplicity,
* but ignore the result and reset this every time setup.
*
* This allows easy user interaction to move the square around.
* */
void moving_boundary_set_square(
GLfloat* temperatures,
size_t width,
size_t height,
size_t square_x,
size_t square_y,
size_t square_width,
size_t square_height,
GLfloat moving_boundary_value
) {
size_t n_temperatures = width * height;
size_t square_height_half = square_height / 2;
size_t square_width_half = square_width / 2;
for (size_t i = 0; i < square_height; ++i) {
for (size_t j = 0; j < square_width; ++j) {
size_t y = square_y + i;
size_t x = square_x + j;
if (
y > square_height_half &&
y < height + square_height_half &&
x > square_width_half &&
x < width + square_width_half
) {
size_t idx = (y - square_height_half) * width + (x - square_width_half);
temperatures[idx] = moving_boundary_value;
}
}
}
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
if (moving_boundary_value_swap) {
moving_boundary_value = 0.0;
}
else {
moving_boundary_value = 0.99;
}
moving_boundary_value_swap = !moving_boundary_value_swap;
}
}
GLint common_get_shader_program(const char* vertex_shader_source, const char* fragment_shader_source) {
enum Consts { INFOLOG_LEN = 512 };
GLchar infoLog[INFOLOG_LEN];
GLint fragment_shader;
GLint shader_program;
GLint success;
GLint vertex_shader;
/* Vertex shader */
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex_shader, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
}
/* Fragment shader */
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment_shader, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
}
/* Link shaders */
shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader_program, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return shader_program;
}
int main(int argc, char** argv) {
GLFWwindow* window;
GLfloat
* temperatures = NULL,
* temperatures2 = NULL,
* temperature_buf = NULL
;
GLint
coord2d_location,
textureSampler_location,
vertexUv_location,
width_location
;
GLuint
compute_program,
ebo,
height,
window_height,
program,
ssbo,
texture,
width,
window_width,
work_group_width,
vao,
vbo
;
char* compute_shader_source, * work_group_width_str;
double
cursor_pos_x = 0.0,
cursor_pos_y = 0.0,
window_grid_ratio_x = 0.0,
window_grid_ratio_y = 0.0
;
int cpu, step = 0, which_boundary;
float conduction_coeff;
size_t
n_temperatures,
square_x,
square_y,
square_width,
square_height
;
unsigned int steps_per_frame, window_x;
/* CLI arguments. */
if (argc > 1) {
width = strtol(argv[1], NULL, 10);
}
else {
width = WIDTH;
}
height = width;
if (argc > 2) {
window_width = strtol(argv[2], NULL, 10);
}
else {
window_width = WINDOW_WIDTH;
}
window_height = window_width;
if (argc > 3) {
work_group_width = strtol(argv[3], NULL, 10);
}
else {
work_group_width = WORK_GROUP_WIDTH;
}
if (argc > 4) {
cpu = (argv[4][0] == '1');
}
else {
cpu = 0;
}
/* TODO remove this when we implement GPU. */
cpu = 1;
/* Must be between 0.0 and 1.0.
*
* Physics allows it to be in 0 / infinity.
*
* Anything greater than 1.0 leads to numeric instabilities
* for our simplistic method. For example, the following:
*
* 1.0
*
* 1.0 0.0 1.0
*
* 1.0
*
* the center point goes above its surroundings on the next time step (2.0)
* for a conduction coefficient of 2.0.
*
* Negative values make temperatures unbounded and breaks energy conservation.
*
* But you obviously will try out "bad" values in the simulation to see what happens.
* The behaviour of this value around 1.99, 2.0, 2.01, 3.0 is specially interesting.
*
* At 0.0, the system does not evolve. Your mouse heat source becomes a permanent pen.
* The close to one, the faster your writting dissipates.
* */
conduction_coeff = 1.0;
if (argc > 5) {
conduction_coeff = strtod(argv[5], NULL);
}
which_boundary = 0;
if (argc > 6) {
which_boundary = strtol(argv[6], NULL, 10);
}
/* Ideally set to make simulation be 60 FPS. */
steps_per_frame = 1;
if (argc > 7) {
steps_per_frame = strtol(argv[7], NULL, 10);
}
window_x = 0;
if (argc > 8) {
window_x = strtol(argv[8], NULL, 10);
}
square_x = width / 2;
square_y = height / 2;
square_width = width / 20;
square_height = height / 20;
window_grid_ratio_x = width / (double)window_width;
window_grid_ratio_y = height / (double)window_height;
/* Window. */
glfwInit();
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
window = glfwCreateWindow(window_width, window_height, __FILE__, NULL, NULL);
glfwSetWindowPos(window, window_x, 0);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glewInit();
/* Shader. */
program = common_get_shader_program(vertex_shader_source, fragment_shader_source);
coord2d_location = glGetAttribLocation(program, "coord2d");
vertexUv_location = glGetAttribLocation(program, "vertexUv");
textureSampler_location = glGetUniformLocation(program, "textureSampler");
if (!cpu) {
/* Compute shader. */
int work_group_width_len = snprintf(NULL, 0, "%d", work_group_width);
size_t compute_shader_source_len = sizeof(compute_shader_source_template) + 2 * work_group_width_len;
compute_shader_source = new char(compute_shader_source_len);
snprintf(
compute_shader_source,
compute_shader_source_len,
compute_shader_source_template,
work_group_width,
work_group_width
);
compute_program = glCreateProgram();
/*compute_program = common_get_compute_program(compute_shader_source);*/
delete[] compute_shader_source;
width_location = glGetUniformLocation(compute_program, "width");
}
/* vbo */
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_xy_uv), vertices_xy_uv, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/* ebo */
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
/* vao */
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(coord2d_location, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(vertices_xy_uv[0]), (GLvoid*)0);
glEnableVertexAttribArray(coord2d_location);
glVertexAttribPointer(vertexUv_location, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(vertices_xy_uv[0]), (GLvoid*)(2 * sizeof(vertices_xy_uv[0])));
glEnableVertexAttribArray(vertexUv_location);
glBindVertexArray(0);
/* ssbo */
srand(time(NULL));
n_temperatures = width * height;
temperatures = new float(n_temperatures * sizeof(temperatures[0]));
/* Initial condition. TODO: make continuous with boundary conditions. */
for (size_t i = 1; i < height - 1; ++i) {
for (size_t j = 1; j < width - 1; ++j) {
temperatures[i * width + j] = 0.0;
}
}
if (cpu) {
temperatures2 = new float(n_temperatures * sizeof(temperatures[0]));
/* Boundary must also be initialized for this buffer,
* since the boundary is never touched after the beginning. */
init_boundary(temperatures2, width, height, which_boundary, step);
}
else {
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, n_temperatures * sizeof(temperatures[0]), temperatures, GL_DYNAMIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
free(temperatures);
}
/* Texture. */
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (!cpu) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, NULL);
/* Bind to image unit so can write to specific pixels from the compute shader. */
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32F);
}
/* Constant state. */
glViewport(0, 0, window_width, window_height);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
/* Main loop. */
void common_fps_init();
while (!glfwWindowShouldClose(window)) {
if (cpu) {
for (
unsigned int steps_this_frame = 0;
steps_this_frame < steps_per_frame;
++steps_this_frame
) {
glfwPollEvents();
glfwGetCursorPos(window, &cursor_pos_x, &cursor_pos_y);
glfwSetMouseButtonCallback(window, mouse_button_callback);
square_x = width - (cursor_pos_x * window_grid_ratio_y);
square_y = cursor_pos_y * window_grid_ratio_y;
moving_boundary_set_square(
temperatures,
width,
height,
square_x,
square_y,
square_width,
square_height,
moving_boundary_value
);
init_boundary(temperatures, width, height, which_boundary, step);
for (unsigned int i = 1; i < height - 1; ++i) {
for (unsigned int j = 1; j < width - 1; ++j) {
size_t idx = i * width + j;
temperatures2[idx] =
(1.0 - conduction_coeff) * temperatures2[idx] +
conduction_coeff * (
temperatures[idx - 1] +
temperatures[idx + 1] +
temperatures[idx - width] +
temperatures[idx + width]
) / 4.0;
}
}
/* Swap old and new. */
temperature_buf = temperatures;
temperatures = temperatures2;
temperatures2 = temperature_buf;
step++;
}
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RED, width, height,
0, GL_RED, GL_FLOAT, temperatures2
);
}
else {
/* Compute. */
glUseProgram(compute_program);
glUniform1ui(width_location, width);
glDispatchCompute((GLuint)width / work_group_width, (GLuint)height / work_group_width, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
}
/* Draw. */
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glUniform1i(textureSampler_location, 0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
common_fps_print();
}
/* Cleanup. */
glDeleteBuffers(1, &ebo);
if (cpu) {
free(temperatures);
free(temperatures2);
}
else {
glDeleteBuffers(1, &ssbo);
}
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glDeleteTextures(1, &texture);
glDeleteProgram(program);
glDeleteProgram(compute_program);
glfwTerminate();
return EXIT_SUCCESS;
}
these are my mistakes :
- common_fps_print(); - not defined
- and a lot of warnings
places that have errors: below with green and red underlines
mistakes in English :)
Diana,
common_fps_print
is defined at: https://github.com/cirosantilli/cpp-cheat/blob/c0f5eca98b205956804575a2716efaabc4d713d3/opengl/common.h#L25 have you tried to include that file or copy the function?
I also generally recommend the following:
- learn how to compile everything from the command line, without the GUI
-
git clone
this repository andgit grep
if there are any other missing definitions
Cino Santilli, soory is it 2D heat equation?
Can I do graphic’s color like this?multicolored
I try add multicolored with rainbow but i can not
Adding just the colors is easy, just map current greyscale to rainbow. The lines and arrows might be hard, I'd look for existing plotting libraries to plug on top.
Cino Santilli, good afternoon 😇 Ok, it is great!!!Can you help me add rainbow color please?)Or send me these libraries 🙏🏼
Diana, sorry but this is too specific for me to do, you have to try and code it yourself, and try Google the libraries yourself.
Hello, Ciro Santilli! in code real time heat equation dt how much?and I can’t find dx and dy?)Please, help me Can you explain why they aren’t in basic equation?)
I'm not sure how to choose the deltas correctly. There are likely discussions about this in books of numerical analysis (error bounds based on how large deltas are), but I didn't learn that unfortunately. It is a very important question.
Sorry, but this code came out with some value)Can you write me there value please, it is important for me🙏🏼
delta’s value, dx dt dy