Loading

Paste #pgcxatbud

  1.  
  2. Particle::Particle()
  3. {
  4.     width = 1600;
  5.     height = 900;
  6.     drawBuf = 1;
  7.     time = 0.0f;
  8.     deltaT = 0.0f;
  9.  
  10.     initScene();
  11. }
  12.  
  13. void Particle::initScene()
  14. {
  15.     compileAndLinkShader();
  16.  
  17.  
  18.     angle = (float)( PI / 2.0f );
  19.     model = glm::mat4(1.0f);
  20.  
  21.     initBuffers();
  22.     const char * filename = "smoke.png";
  23.  
  24.     FREE_IMAGE_FORMAT imageFormat = FIF_UNKNOWN;
  25.  
  26.     FIBITMAP* m_bitmap;
  27.  
  28.     struct stat fileAttribute;
  29.     bool fileExists = stat(filename, &fileAttribute) == 0;
  30.  
  31.     assert(fileExists);
  32.  
  33.     imageFormat = FreeImage_GetFileType(filename);
  34.  
  35.     //if still unknown, try to guess the file format from the file extension
  36.     if (imageFormat == FIF_UNKNOWN) {
  37.         imageFormat = FreeImage_GetFIFFromFilename(filename);
  38.     }
  39.  
  40.     //still unknown, we're boned.
  41.     if (imageFormat == FIF_UNKNOWN) {
  42.     }
  43.  
  44.     //check that the plugin has reading capabilities for this file and load the file
  45.     if (FreeImage_FIFSupportsReading(imageFormat)) {
  46.         m_bitmap = FreeImage_Load(imageFormat, filename);
  47.     } else {
  48.         // we can't read this!
  49.     }
  50.  
  51.     int m_width = FreeImage_GetWidth(m_bitmap);
  52.     int m_height = FreeImage_GetHeight(m_bitmap);
  53.  
  54.     if (m_width == 0 || m_height == 0) {
  55.     }
  56.  
  57.     glGenTextures(1, &m_textureID);
  58.     glBindTexture(GL_TEXTURE_2D, m_textureID);
  59.  
  60.     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
  61.     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
  62.  
  63.             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  64.             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  65. //            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  66. //            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  67. //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  68. //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  69.     BYTE* bits = FreeImage_GetBits(m_bitmap);
  70.  
  71.     m_internal_format = GL_RGBA;
  72.     m_image_format = GL_RGBA;
  73.     m_level = 0;
  74.     m_border = 0;
  75.     glTexImage2D(GL_TEXTURE_2D, m_level, m_internal_format, m_width, m_height, m_border, m_image_format, GL_UNSIGNED_BYTE, bits);
  76.  
  77. }
  78.  
  79. void Particle::initBuffers()
  80. {
  81.     nParticles = 1000;
  82.  
  83.     // Generate the buffers
  84.     glGenBuffers(2, posBuf);    // position buffers
  85.     glGenBuffers(2, velBuf);    // velocity buffers
  86.     glGenBuffers(2, startTime); // Start time buffers
  87.     glGenBuffers(1, &initVel);  // Initial velocity buffer (never changes, only need one)
  88.  
  89.     // Allocate space for all buffers
  90.     int size = nParticles * 3 * sizeof(float);
  91.     glBindBuffer(GL_ARRAY_BUFFER, posBuf[0]);
  92.     glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_COPY);
  93.     glBindBuffer(GL_ARRAY_BUFFER, posBuf[1]);
  94.     glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_COPY);
  95.     glBindBuffer(GL_ARRAY_BUFFER, velBuf[0]);
  96.     glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_COPY);
  97.     glBindBuffer(GL_ARRAY_BUFFER, velBuf[1]);
  98.     glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_COPY);
  99.     glBindBuffer(GL_ARRAY_BUFFER, initVel);
  100.     glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW);
  101.     glBindBuffer(GL_ARRAY_BUFFER, startTime[0]);
  102.     glBufferData(GL_ARRAY_BUFFER, nParticles * sizeof(float), NULL, GL_DYNAMIC_COPY);
  103.     glBindBuffer(GL_ARRAY_BUFFER, startTime[1]);
  104.     glBufferData(GL_ARRAY_BUFFER, nParticles * sizeof(float), NULL, GL_DYNAMIC_COPY);
  105.  
  106.     // Fill the first position buffer with zeroes
  107.     GLfloat *data = new GLfloat[nParticles * 3];
  108.     for( int i = 0; i < nParticles * 3; i += 3 ) {
  109.         data[i] = 0.0f;
  110.         data[i+1] = 0.0f;
  111.         data[i+2] = 0.0f;
  112.     }
  113.  
  114.     glBindBuffer(GL_ARRAY_BUFFER, posBuf[0]);
  115.     glBufferSubData(GL_ARRAY_BUFFER, 0, size, data);
  116.  
  117.     // Fill the first velocity buffer with random velocities
  118.     float theta, phi, velocity;
  119.     glm::vec3 v(0.0f);
  120.     for( int i = 0; i < nParticles; i++ ) {
  121.         theta = glm::mix(0.0f, (float)PI / 1.5f, randFloat());
  122.         phi = glm::mix(0.0f, (float)TWOPI, randFloat());
  123.  
  124.         v.x = sinf(theta) * cosf(phi);
  125.         v.y = cosf(theta);
  126.         v.z = sinf(theta) * sinf(phi);
  127.  
  128.         velocity = glm::mix(0.1f,0.2f,randFloat());
  129.         v = glm::normalize(v) * velocity;
  130.  
  131.         data[3*i]   = v.x;
  132.         data[3*i+1] = v.y;
  133.         data[3*i+2] = v.z;
  134.     }
  135.     glBindBuffer(GL_ARRAY_BUFFER,velBuf[0]);
  136.     glBufferSubData(GL_ARRAY_BUFFER, 0, size, data);
  137.     glBindBuffer(GL_ARRAY_BUFFER,initVel);
  138.     glBufferSubData(GL_ARRAY_BUFFER, 0, size, data);
  139.  
  140.     // Fill the first start time buffer
  141.     delete [] data;
  142.     data = new GLfloat[nParticles];
  143.     float time = 0.0f;
  144.     float rate = 0.01f;
  145.     for( int i = 0; i < nParticles; i++ ) {
  146.         data[i] = time;
  147.         time += rate;
  148.     }
  149.     glBindBuffer(GL_ARRAY_BUFFER,startTime[0]);
  150.     glBufferSubData(GL_ARRAY_BUFFER, 0, nParticles * sizeof(float), data);
  151.  
  152.     glBindBuffer(GL_ARRAY_BUFFER,0);
  153.     delete [] data;
  154.  
  155.     // Create vertex arrays for each set of buffers
  156.     glGenVertexArrays(2, particleArray);
  157.  
  158.     // Set up particle array 0
  159.     glBindVertexArray(particleArray[0]);
  160.     glBindBuffer(GL_ARRAY_BUFFER, posBuf[0]);
  161.     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
  162.     glEnableVertexAttribArray(0);
  163.  
  164.     glBindBuffer(GL_ARRAY_BUFFER, velBuf[0]);
  165.     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
  166.     glEnableVertexAttribArray(1);
  167.  
  168.     glBindBuffer(GL_ARRAY_BUFFER, startTime[0]);
  169.     glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, NULL);
  170.     glEnableVertexAttribArray(2);
  171.  
  172.     glBindBuffer(GL_ARRAY_BUFFER, initVel);
  173.     glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, NULL);
  174.     glEnableVertexAttribArray(3);
  175.  
  176.     // Set up particle array 1
  177.     glBindVertexArray(particleArray[1]);
  178.     glBindBuffer(GL_ARRAY_BUFFER, posBuf[1]);
  179.     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
  180.     glEnableVertexAttribArray(0);
  181.  
  182.     glBindBuffer(GL_ARRAY_BUFFER, velBuf[1]);
  183.     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
  184.     glEnableVertexAttribArray(1);
  185.  
  186.     glBindBuffer(GL_ARRAY_BUFFER, startTime[1]);
  187.     glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, NULL);
  188.     glEnableVertexAttribArray(2);
  189.  
  190.     glBindBuffer(GL_ARRAY_BUFFER, initVel);
  191.     glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, NULL);
  192.     glEnableVertexAttribArray(3);
  193.  
  194.     glBindVertexArray(0);
  195.  
  196.     // Setup the feedback objects
  197.     glGenTransformFeedbacks(2, feedback);
  198.  
  199.     // Transform feedback 0
  200.     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedback[0]);
  201.     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, posBuf[0]);
  202.     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, velBuf[0]);
  203.     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, startTime[0]);
  204.  
  205.     // Transform feedback 1
  206.     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedback[1]);
  207.     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, posBuf[1]);
  208.     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, velBuf[1]);
  209.     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, startTime[1]);
  210.  
  211.     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
  212.     glBindBuffer(GL_ARRAY_BUFFER, 0);
  213. }
  214.  
  215. float Particle::randFloat() {
  216.     return ((float)rand() / RAND_MAX);
  217. }
  218.  
  219. void Particle::render()
  220. {
  221.     static float t = 0.0f;
  222.     t += 1.0/60.0;
  223.     deltaT = t - time;
  224.     time = t;
  225.  
  226.     glEnable(GL_PROGRAM_POINT_SIZE);
  227. //    glEnable(GL_BLEND);
  228.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  229.  
  230.     glUseProgram(shader_program);
  231.  
  232.  
  233.     GLint lifetimeLoc = glGetUniformLocation(shader_program, "ParticleLifetime");
  234.     glUniform1f(lifetimeLoc, 6.0f);
  235.  
  236.  
  237.     GLint accelLoc = glGetUniformLocation(shader_program, "Accel");
  238.     glUniform3f(accelLoc, -0.1f, 0.1f, 0.0f);
  239.  
  240.     glActiveTexture(GL_TEXTURE0);
  241.     glBindTexture(GL_TEXTURE_2D, m_textureID);
  242.  
  243.     GLint texLoc = glGetUniformLocation(shader_program, "ParticleTex");
  244.     glUniform1i(texLoc, 0);
  245.  
  246.     // Update pass
  247.     GLint passTypeLoc = glGetUniformLocation(shader_program, "passType");
  248.  
  249.     glUniform1i(passTypeLoc, 0);
  250.  
  251.     GLint timeLoc = glGetUniformLocation(shader_program, "Time");
  252.     glUniform1f(timeLoc, time);
  253.  
  254.     GLint deltaTLoc = glGetUniformLocation(shader_program, "H");
  255.     glUniform1f(deltaTLoc, deltaT);
  256.  
  257.  
  258.     setMatrices();
  259.     // Update pass
  260.  
  261. printf("TIME:! %f\n", time);
  262.  
  263.     glEnable(GL_RASTERIZER_DISCARD);
  264.  
  265.     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedback[drawBuf]);
  266.  
  267.     glBeginTransformFeedback(GL_POINTS);
  268.       glBindVertexArray(particleArray[1-drawBuf]);
  269.       glDrawArrays(GL_POINTS, 0, nParticles);
  270.     glEndTransformFeedback();
  271.  
  272.     glDisable(GL_RASTERIZER_DISCARD);
  273.  
  274.     // Render pass
  275.     glUniform1i(passTypeLoc, 1);
  276.     view = glm::lookAt(glm::vec3(3.0f * cosf(angle),1.5f,3.0f * sinf(angle)), glm::vec3(0.0f,1.5f,0.0f), glm::vec3(0.0f,1.0f,0.0f));
  277.     setMatrices();
  278.  
  279.     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
  280.     glBindVertexArray(particleArray[drawBuf]);
  281.     glDrawArrays(GL_POINTS, 0, nParticles);
  282.  
  283.     glBindBuffer(GL_ARRAY_BUFFER, 0);
  284.     glBindVertexArray(0);
  285.     glUseProgram(0);
  286.     // Swap buffers
  287.     drawBuf = 1 - drawBuf;
  288. }
  289.  
  290. void Particle::setMatrices()
  291. {
  292.     glm::mat4 mvp = view * model;
  293.     width = 1600;
  294.     height = 900;
  295.     projection = glm::perspective(60.0f, (float)width/height, 0.3f, 100.0f);
  296.  
  297.     glm::mat4 final = projection* mvp;
  298.     int mvpLoc = glGetUniformLocation(shader_program, "MVP");
  299.     glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, &final[0][0]);
  300. }
  301.  
  302. void Particle::resize(int w, int h)
  303. {
  304.     glViewport(0,0,w,h);
  305.     width = w = 1600;
  306.     height = h = 900;
  307.     projection = glm::perspective(60.0f, (float)w/h, 0.3f, 100.0f);
  308. }
  309.  
  310. // helper to check and display for shader compiler errors
  311. bool Particle::check_shader_compile_status(GLuint obj)
  312. {
  313.     GLint status;
  314.     glGetShaderiv(obj, GL_COMPILE_STATUS, &status);
  315.     if(status == GL_FALSE)
  316.     {
  317.         GLint length;
  318.         glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
  319.         std::vector<char> log(length);
  320.         glGetShaderInfoLog(obj, length, &length, &log[0]);
  321.         std::cerr << &log[0];
  322.         return false;
  323.     }
  324.     return true;
  325. }
  326.  
  327. // helper to check and display for shader linker error
  328. bool Particle::check_program_link_status(GLuint obj)
  329. {
  330.     GLint status;
  331.     glGetProgramiv(obj, GL_LINK_STATUS, &status);
  332.     if(status == GL_FALSE)
  333.     {
  334.         GLint length;
  335.         glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
  336.         std::vector<char> log(length);
  337.         glGetProgramInfoLog(obj, length, &length, &log[0]);
  338.         std::cerr << &log[0];
  339.         return false;
  340.     }
  341.     return true;
  342. }
  343.  
  344. std::string Particle::loadFile(const char* fileName)
  345. {
  346.     struct stat fileAttribute;
  347.     bool fileExists = stat(fileName, &fileAttribute) == 0;
  348.     assert(fileExists);
  349.  
  350.     std::ifstream in(fileName);
  351.  
  352.     std::stringstream buffer;
  353.     buffer << in.rdbuf();
  354.  
  355.     std::string contents(buffer.str());
  356.  
  357.     return contents;
  358. }
  359.  
  360. void Particle::compileAndLinkShader()
  361. {
  362.     GLuint fragment_shader;
  363.     GLuint vertex_shader;
  364.  
  365.     std::string vertex_source = loadFile("smoke.vs");
  366.  
  367.     std::string fragment_source = loadFile("smoke.fs");
  368.  
  369.     //    // create and compiler vertex shader
  370.     vertex_shader = glCreateShader(GL_VERTEX_SHADER);
  371.  
  372.     const char* vertexArray = vertex_source.c_str();
  373.  
  374.     glShaderSource(vertex_shader, 1, &vertexArray, NULL);
  375.     glCompileShader(vertex_shader);
  376.     if(!check_shader_compile_status(vertex_shader))
  377.     {
  378.         exit(1);
  379.     }
  380.  
  381.     // create and compiler fragment shader
  382.     fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
  383.  
  384.     const char* fragmentArray = fragment_source.c_str();
  385.     glShaderSource(fragment_shader, 1, &fragmentArray, NULL);
  386.     glCompileShader(fragment_shader);
  387.     if(!check_shader_compile_status(fragment_shader))
  388.     {
  389.         exit(1);
  390.     }
  391.  
  392.     // create program
  393.     shader_program = glCreateProgram();
  394.  
  395.     // attach shaders
  396.     glAttachShader(shader_program, vertex_shader);
  397.     glAttachShader(shader_program, fragment_shader);
  398.  
  399.     const char * outputNames[] = { "Position", "Velocity", "StartTime" };
  400.     glTransformFeedbackVaryings(shader_program, 3, outputNames, GL_SEPARATE_ATTRIBS);
  401.  
  402.     // link the program and check for errors
  403.     glLinkProgram(shader_program);
  404.     check_program_link_status(shader_program);
  405.  
  406.     glUseProgram(shader_program);
  407. }
  408.  

Comments