Files
rez_demo/GL_STUFF/SOURCES/EFFECTS/CRT_shader.cpp

276 lines
9.0 KiB
C++
Raw Normal View History

#include "../../HEADERS/EFFECTS/CRT_shader.h"
#include "../../HEADERS/UTILS/ShaderMaker.h"
#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);
}