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