2026-03-16 00:10:52 +01:00
|
|
|
#include "../../../headers/GL_STUFF/EFFECTS/CRT_shader.h"
|
|
|
|
|
#include "../../../headers/GL_STUFF/UTILS/ShaderMaker.h"
|
2025-07-03 01:26:25 +02:00
|
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
int CRT_Shader::CRT_HORIZONTAL_PIXELS;
|
|
|
|
|
int CRT_Shader::CRT_VERTICAL_PIXELS;
|
|
|
|
|
int CRT_Shader::CRT_WIDTH;
|
|
|
|
|
int CRT_Shader::CRT_HEIGHT;
|
|
|
|
|
int CRT_Shader::PARTICLE_COUNT;
|
|
|
|
|
int CRT_Shader::PARTICLE_GROUP_COUNT;
|
|
|
|
|
bool CRT_Shader::CRT_FLIP_Y;
|
|
|
|
|
SIM_PRECISION CRT_Shader::resolution;
|
|
|
|
|
|
|
|
|
|
vec3 CRT_Shader::scaleToZOne(vec3 vector) {
|
|
|
|
|
return (1 / vector.z) * vector;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vec3 CRT_Shader::crt_emission_angle(int index) {
|
|
|
|
|
|
|
|
|
|
int xCoord = (index % CRT_HORIZONTAL_PIXELS) - (CRT_HORIZONTAL_PIXELS / 2);
|
|
|
|
|
int yCoord = (index / CRT_HORIZONTAL_PIXELS) - (CRT_VERTICAL_PIXELS / 2);
|
|
|
|
|
|
|
|
|
|
float longCat = CRT_DEPTH;
|
|
|
|
|
float shortCatX = CRT_PIXEL_LENGTH * xCoord;
|
|
|
|
|
float shortCatY = CRT_PIXEL_LENGTH * yCoord;
|
|
|
|
|
vec3 res = vec3(shortCatX, -shortCatY, 1.0);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CRT_Shader::createRenderShader() {
|
|
|
|
|
string vertexSh = resourceRoot + "vertexShader_particles.glsl";
|
|
|
|
|
string fragmentSh = resourceRoot + "fragmentShader_particles.glsl";
|
|
|
|
|
render_prog = ShaderMaker::createProgram(&vertexSh[0], &fragmentSh[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CRT_Shader::createComputeShader() {
|
|
|
|
|
GLenum ErrorCheckValue = glGetError();
|
|
|
|
|
string compSh = resourceRoot + "computeShader_particles.glsl";
|
|
|
|
|
GLchar* VertexShader = ShaderMaker::readShaderSource(&compSh[0]);
|
|
|
|
|
//Visualizzo sulla console il CODICE VERTEX SHADER
|
|
|
|
|
std::cout << VertexShader;
|
|
|
|
|
|
|
|
|
|
//Generiamo un identificativo per il vertex shader
|
|
|
|
|
GLuint computeShaderId = glCreateShader(GL_COMPUTE_SHADER);
|
|
|
|
|
//Associamo all'identificativo il codice del vertex shader
|
|
|
|
|
glShaderSource(computeShaderId, 1, (const char**)&VertexShader, NULL);
|
|
|
|
|
//Compiliamo il Vertex SHader
|
|
|
|
|
glCompileShader(computeShaderId);
|
|
|
|
|
|
|
|
|
|
int success;
|
|
|
|
|
char infoLog[512];
|
|
|
|
|
glGetShaderiv(computeShaderId, GL_COMPILE_STATUS, &success);
|
|
|
|
|
if (!success) {
|
|
|
|
|
glGetShaderInfoLog(computeShaderId, 512, NULL, infoLog);
|
|
|
|
|
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ErrorCheckValue = glGetError();
|
|
|
|
|
std::cout << ErrorCheckValue;
|
|
|
|
|
|
|
|
|
|
if (ErrorCheckValue != GL_NO_ERROR)
|
|
|
|
|
{
|
|
|
|
|
fprintf(
|
|
|
|
|
stderr,
|
|
|
|
|
"ERROR: Could not create the shaders: %s \n",
|
|
|
|
|
gluErrorString(ErrorCheckValue)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
//Creiamo un identificativo di un eseguibile e gli colleghiamo i due shader compilati
|
|
|
|
|
compute_prog = glCreateProgram();
|
|
|
|
|
|
|
|
|
|
glAttachShader(compute_prog, computeShaderId);
|
|
|
|
|
glLinkProgram(compute_prog);
|
|
|
|
|
dt_location = glGetUniformLocation(compute_prog, "dt");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CRT_Shader::buffersSetup() {
|
|
|
|
|
GLuint buffers[5];
|
|
|
|
|
GLuint textures[3];
|
|
|
|
|
glGenBuffers(5, buffers);
|
|
|
|
|
start_position_buffer = buffers[0];
|
|
|
|
|
end_position_buffer = buffers[1];
|
|
|
|
|
velocity_buffer = buffers[2];
|
|
|
|
|
color_buffer = buffers[3];
|
|
|
|
|
magnets_buffer = buffers[4];
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, magnets_buffer);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(vec4), NULL, GL_DYNAMIC_COPY); //dynamic copy ???
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
|
attractors[i] = vec4();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, start_position_buffer);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, PARTICLE_COUNT * sizeof(vec4), NULL, GL_DYNAMIC_COPY);
|
|
|
|
|
//Map the position buffer
|
|
|
|
|
vec4* positions = (vec4*)glMapNamedBufferRangeEXT(start_position_buffer, 0, PARTICLE_COUNT * sizeof(vec4), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < PARTICLE_COUNT; i++)
|
|
|
|
|
{
|
|
|
|
|
positions[i] = vec4(0, 0, -CRT_DEPTH, 0);
|
|
|
|
|
}
|
|
|
|
|
glUnmapNamedBufferEXT(start_position_buffer);
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, end_position_buffer);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, PARTICLE_COUNT * sizeof(vec4), NULL, GL_DYNAMIC_COPY);
|
|
|
|
|
glUnmapNamedBufferEXT(end_position_buffer);
|
|
|
|
|
|
|
|
|
|
//initialization of the velocity buffer
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, velocity_buffer);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, PARTICLE_COUNT * sizeof(vec4), NULL, GL_DYNAMIC_COPY);
|
|
|
|
|
vec4* velocities = (vec4*)glMapBufferRange(GL_ARRAY_BUFFER, 0, PARTICLE_COUNT * sizeof(vec4), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < CRT_VERTICAL_PIXELS * CRT_HORIZONTAL_PIXELS; i++)
|
|
|
|
|
{
|
|
|
|
|
velocities[i] = glm::vec4(crt_emission_angle(i), 0.0);
|
|
|
|
|
}
|
|
|
|
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
//initialization of the color buffer
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, PARTICLE_COUNT * COLOR_CHANNELS * sizeof(unsigned char), NULL, GL_DYNAMIC_COPY);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glGenTextures(3, textures);
|
|
|
|
|
|
|
|
|
|
velocity_tbo = textures[0];
|
|
|
|
|
start_position_tbo = textures[1];
|
|
|
|
|
end_position_tbo = textures[2];
|
|
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER, velocity_tbo);
|
|
|
|
|
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, velocity_buffer);
|
|
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER, start_position_tbo);
|
|
|
|
|
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, start_position_buffer);
|
|
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER, end_position_tbo);
|
|
|
|
|
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, end_position_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CRT_Shader::VAOsSetup() {
|
|
|
|
|
glGenVertexArrays(1, &render_vao);
|
|
|
|
|
glBindVertexArray(render_vao);
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, end_position_buffer);
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, velocity_buffer);
|
|
|
|
|
glEnableVertexAttribArray(1);
|
|
|
|
|
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
|
|
|
|
/////////////////////
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
|
|
|
|
|
glEnableVertexAttribArray(2);
|
|
|
|
|
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, 4 * sizeof(unsigned char), 0);
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, magnets_buffer);
|
|
|
|
|
glEnableVertexAttribArray(3);
|
|
|
|
|
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CRT_Shader::CRT_Shader() {
|
|
|
|
|
|
|
|
|
|
createRenderShader();
|
|
|
|
|
createComputeShader();
|
|
|
|
|
float top = crt_emission_angle(0).y;
|
|
|
|
|
float bottom = crt_emission_angle((PARTICLE_COUNT)-1).y;
|
|
|
|
|
if (CRT_FLIP_Y) {
|
|
|
|
|
float swap = top;
|
|
|
|
|
top = bottom;
|
|
|
|
|
bottom = swap;
|
|
|
|
|
}
|
|
|
|
|
orthoMat = ortho(crt_emission_angle(0).x,
|
|
|
|
|
crt_emission_angle((PARTICLE_COUNT) - 1).x,
|
|
|
|
|
bottom,
|
|
|
|
|
top,
|
|
|
|
|
-1.0f,
|
|
|
|
|
1.0f);
|
|
|
|
|
|
|
|
|
|
buffersSetup();
|
|
|
|
|
VAOsSetup();
|
|
|
|
|
|
|
|
|
|
CS_LTF = vec3(scaleToZOne(crt_emission_angle(0)).x, scaleToZOne(crt_emission_angle(0)).y, 0);
|
|
|
|
|
CS_RBF = vec3(scaleToZOne(crt_emission_angle((PARTICLE_COUNT) - 1)).x, scaleToZOne(crt_emission_angle((PARTICLE_COUNT) - 1)).y, 0);
|
|
|
|
|
CS_LTN = vec3(-0.1, 0.1, -1);
|
|
|
|
|
CS_RBN = vec3(0.1, -0.1, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CRT_Shader::draw(unsigned int ONE_TICK_MS, unsigned int timePassed) {
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, magnets_buffer);
|
|
|
|
|
vec4* attractors = (vec4*)glMapNamedBufferRangeEXT(magnets_buffer, 0, 8 * sizeof(vec4), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
|
attractors[i] = this->attractors[i];
|
|
|
|
|
|
|
|
|
|
glUnmapNamedBufferEXT(magnets_buffer);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//activate the compute program and bind the position
|
|
|
|
|
//and velocity buffers
|
|
|
|
|
glUseProgram(compute_prog);
|
|
|
|
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, magnets_buffer);
|
|
|
|
|
glBindImageTexture(0, velocity_tbo, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
|
|
|
|
glBindImageTexture(1, start_position_tbo, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
|
|
|
|
glBindImageTexture(2, end_position_tbo, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
|
|
|
|
|
|
|
|
|
|
glUniform3f(glGetUniformLocation(compute_prog, "nearTopLeft"), CS_LTN.x, CS_LTN.y, CS_LTN.z);
|
|
|
|
|
glUniform3f(glGetUniformLocation(compute_prog, "nearBottomRight"), CS_RBN.x, CS_RBN.y, CS_RBN.z);
|
|
|
|
|
glUniform3f(glGetUniformLocation(compute_prog, "farTopLeft"), CS_LTF.x, CS_LTF.y, CS_LTF.z);
|
|
|
|
|
glUniform3f(glGetUniformLocation(compute_prog, "farBottomRight"), CS_RBF.x, CS_RBF.y, CS_RBF.z);
|
|
|
|
|
//set delta time
|
|
|
|
|
glUniform1f(dt_location, 1e-2 * pow(4, (int) resolution));
|
|
|
|
|
|
|
|
|
|
//dispatch the compute shader
|
|
|
|
|
glDispatchCompute(PARTICLE_GROUP_COUNT, 1, 1);
|
|
|
|
|
|
|
|
|
|
//ensure that writes by the compute shader have completed
|
|
|
|
|
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
|
|
|
|
|
|
|
|
|
glUseProgram(render_prog);
|
|
|
|
|
glUniformMatrix4fv(glGetUniformLocation(render_prog, "mvp"), 1, GL_FALSE, value_ptr(orthoMat));
|
|
|
|
|
|
|
|
|
|
glUniform1ui(glGetUniformLocation(render_prog, "pixelWidth"), CRT_PIXEL_SCALE * 1000 * CRT_PIXEL_LENGTH);
|
|
|
|
|
|
|
|
|
|
glBindVertexArray(render_vao);
|
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
glBlendFunc(GL_ONE, GL_ONE);
|
|
|
|
|
glPointSize(CRT_PIXEL_SCALE);
|
|
|
|
|
glDrawArrays(GL_POINTS, 0, PARTICLE_COUNT);
|
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CRT_Shader::setMagnet(int index, vec4 positionAndMass) {
|
|
|
|
|
float vieww = scaleToZOne(crt_emission_angle((PARTICLE_COUNT) - 1)).x - scaleToZOne(crt_emission_angle(0)).x;
|
|
|
|
|
float viewh = scaleToZOne(crt_emission_angle((PARTICLE_COUNT) - 1)).y - scaleToZOne(crt_emission_angle(0)).y;
|
|
|
|
|
magx = vieww * (positionAndMass.x - CRT_WIDTH / 2) / ((float)CRT_WIDTH);
|
|
|
|
|
magy = viewh * (positionAndMass.y - CRT_HEIGHT / 2) / ((float)CRT_HEIGHT);
|
|
|
|
|
attractors[index] = vec4(magx, magy, positionAndMass.z, positionAndMass.w * pow(4, (int)-resolution));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
DOES ANYTHING CHANGE WITH CRT_FLIP_Y ???
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float CRT_Shader::getLeftBound() {
|
|
|
|
|
return -CRT_WIDTH / 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float CRT_Shader::getRightBound() {
|
|
|
|
|
return CRT_WIDTH / 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float CRT_Shader::getBottomBound() {
|
|
|
|
|
return -(CRT_HEIGHT / 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float CRT_Shader::getTopBound() {
|
|
|
|
|
return (CRT_HEIGHT / 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CRT_Shader::loadColorFromFramebuffer(GLuint FBO) {
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
|
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, color_buffer);
|
|
|
|
|
glReadPixels(0, 0, CRT_HORIZONTAL_PIXELS, CRT_VERTICAL_PIXELS, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
|
|
|
|
}
|