| // Copyright 2012 The Emscripten Authors. All rights reserved. |
| // Emscripten is available under two separate licenses, the MIT license and the |
| // University of Illinois/NCSA Open Source License. Both these licenses can be |
| // found in the LICENSE file. |
| |
| #define GL_GLEXT_PROTOTYPES |
| #define EGL_EGLEXT_PROTOTYPES |
| #include <cassert> |
| #include <cmath> |
| #include <iostream> |
| #include <vector> |
| extern "C" { |
| #include <GL/gl.h> |
| #include <GL/glut.h> |
| } |
| static const char vertex_shader[] = |
| "#ifdef GL_ES\n" |
| "precision lowp float;\n" |
| "#endif\n" |
| "attribute float indices;\n" |
| "uniform sampler2D nodeInfo;\n" |
| "varying vec4 color;" |
| "\n" |
| "void main(void)\n" |
| "{\n" |
| " float s = (indices + 0.5) / 512.; \n" |
| " vec4 v = texture2D(nodeInfo, vec2( s, 0.5));\n" |
| " gl_Position = vec4(v.x, v.y, 0.5, 1.);\n" |
| " gl_PointSize = v.z;\n" |
| " color = vec4(0.5 + v.w/2., 0.5 + 0.5 * v.w/2., 0.5, 1);\n" |
| "}\n"; |
| static const char fragment_shader[] = |
| "#ifdef GL_ES\n" |
| "precision lowp float;\n" |
| "#endif\n" |
| "\n" |
| "varying vec4 color;\n" |
| "void main(void)\n" |
| "{\n" |
| " float dst = distance(vec2(0.5, 0.5), gl_PointCoord); \n" |
| " gl_FragColor = color;\n" |
| " if ( dst > 0.3) {" |
| " gl_FragColor = vec4(0., 0., 0.5, 0.2);\n" |
| "}\n" |
| "if ( dst > 0.5) discard;\n" |
| "}"; |
| struct NodeInfo { //structure that we want to transmit to our shaders |
| float x; |
| float y; |
| float s; |
| float c; |
| }; |
| GLuint nodeTexture; //texture id used to bind |
| GLuint nodeSamplerLocation; //shader sampler address |
| GLuint indicesAttributeLocation; //shader attribute address |
| GLuint indicesVBO; //Vertex Buffer Object Id; |
| const int nbNodes = 512; |
| NodeInfo * data = new NodeInfo[nbNodes]; //our data that will be transmitted using float texture. |
| double alpha = 0; //use to make a simple funny effect; |
| static void updateFloatTexture() { |
| int count = 0; |
| for (float x=0; x < nbNodes; ++x ) { |
| data[count].x = 0.2*pow(cos(alpha), 3) + (sin(alpha)*3. + 3.5) * x/nbNodes * cos(alpha + x/nbNodes * 16. * M_PI); |
| data[count].y = 0.2*pow(sin(alpha), 3) + (sin(alpha)*3. + 3.5) * x/nbNodes * sin(alpha + x/nbNodes * 16. * M_PI); |
| data[count].s = (16. + 16. * cos(alpha + x/nbNodes * 32. * M_PI)) + 8.;// * fmod(x/nbNodes + alpha, 1.) + 5.; |
| data[count].c = 0.5 + 0.5 * sin(alpha + x/nbNodes * 32. * M_PI); |
| ++count; |
| } |
| glBindTexture(GL_TEXTURE_2D, nodeTexture); |
| #ifdef __EMSCRIPTEN__ // In GLES2 and WebGL1, we must use unsized texture internal formats. |
| const GLenum internalFormat = GL_RGBA; |
| #else |
| // In desktop GL, we can also use sized internal formats. |
| const GLenum internalFormat = GL_RGBA32F; |
| #endif |
| glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, nbNodes, 1, 0, GL_RGBA, GL_FLOAT, data); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glBindTexture(GL_TEXTURE_2D, NULL); |
| alpha -= 0.001; |
| } |
| static void glut_draw_callback(void) { |
| glDisable(GL_CULL_FACE); |
| glDisable(GL_DEPTH_TEST); |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| glClearColor(1., 1., 1., 0.); |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| glActiveTexture(GL_TEXTURE0); |
| updateFloatTexture(); //we change the texture each time to create the effect (it is just for the test) |
| glBindTexture(GL_TEXTURE_2D, nodeTexture); |
| glUniform1i(nodeSamplerLocation, 0); |
| glEnableVertexAttribArray(0); |
| glBindBuffer(GL_ARRAY_BUFFER, indicesVBO); |
| glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL); |
| glDrawArrays(GL_POINTS, 0, nbNodes); |
| glutSwapBuffers(); |
| } |
| GLuint createShader(const char source[], int type) { |
| GLint status; |
| char msg[512]; |
| GLuint shader = glCreateShader(type); |
| glShaderSource(shader, 1, (const GLchar**)(&source), NULL); |
| glCompileShader(shader); |
| glGetShaderiv(shader, GL_COMPILE_STATUS, &status); |
| if (status == GL_FALSE) { |
| glGetShaderInfoLog(shader, sizeof msg, NULL, msg); |
| std::cout << "Shader info: \"" << msg << "\"" << std::endl; |
| } |
| assert(status == GL_TRUE); |
| return shader; |
| } |
| static void gl_init(void) { |
| GLuint program = glCreateProgram(); |
| glAttachShader(program, createShader(vertex_shader , GL_VERTEX_SHADER)); |
| glAttachShader(program, createShader(fragment_shader, GL_FRAGMENT_SHADER)); |
| glLinkProgram(program); |
| GLint status; |
| char msg[512]; |
| glGetProgramiv(program, GL_LINK_STATUS, &status); |
| if (status == GL_FALSE) { |
| glGetProgramInfoLog(program, sizeof msg, NULL, msg); |
| std::cout << "info: \"" << msg << "\"" << std::endl; |
| } |
| assert(status == GL_TRUE); |
| glUseProgram(program); |
| std::vector<float> elements(nbNodes); |
| int count = 0; |
| for (float x=0; x < nbNodes; ++x ) { |
| elements[count] = count; |
| ++count; |
| } |
| /*Create one texture to store all the needed information */ |
| glGenTextures(1, &nodeTexture); |
| /* Store the vertices in a vertex buffer object (VBO) */ |
| glGenBuffers(1, &indicesVBO); |
| glBindBuffer(GL_ARRAY_BUFFER, indicesVBO); |
| glBufferData(GL_ARRAY_BUFFER, elements.size() * sizeof(float), &elements[0], GL_STATIC_DRAW); |
| /* Get the locations of the uniforms so we can access them */ |
| nodeSamplerLocation = glGetUniformLocation(program, "nodeInfo"); |
| glBindAttribLocation(program, 0, "indices"); |
| #ifndef __EMSCRIPTEN__ // GLES2 & WebGL do not have these, only pre 3.0 desktop GL and compatibility mode GL3.0+ GL do. |
| //Enable glPoint size in shader, always enable in Open Gl ES 2. |
| glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); |
| glEnable(GL_POINT_SPRITE); |
| #endif |
| } |
| int main(int argc, char *argv[]) { |
| glutInit(&argc, argv); |
| glutInitWindowSize(640, 480); |
| glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); |
| glutCreateWindow("Simple FLOAT Texture Test"); |
| /* Set up glut callback functions */ |
| glutDisplayFunc(glut_draw_callback ); |
| gl_init(); |
| glutMainLoop(); |
| return 0; |
| } |
| |
| |