Title::Title(const QByteArray &encodedTitle, const QString &language) : language(language), fileNr(255) { if (encodedTitle.length() < 15) return; encTitle=encodedTitle; QByteArray escapeData(encodedTitle.left(2)); QByteArray positionData(encodedTitle.mid(2, 13)); QDataStream escapeDataStream(escapeData); escapeDataStream.setByteOrder(QDataStream::LittleEndian); quint16 escapes; escapeDataStream >> escapes; for (int i = 0; i < 13; i ++) if (escapes & (1 << i)) positionData[i] = '\n'; QDataStream positionDataStream(positionData); positionDataStream.setByteOrder(QDataStream::LittleEndian); positionDataStream >> fileNr >> blockStart >> blockOffset >> articleLength; int titleLenBytes = encodedTitle.length() - 15; if (titleLenBytes > 0 && encodedTitle[encodedTitle.length() - 1] == '\n') titleLenBytes --; name = QString::fromUtf8(encodedTitle.mid(15, titleLenBytes).constData(), titleLenBytes); }
void TerrainTessellationScene::prepareVertexBuffers( QSize heightMapSize ) { // Generate patch primitive data to cover the heightmap texture assuming // one heightmap sample per triangle at maximum tessellation level. // Each patch consists of a single point located at the lower-left corner // of a rectangle (in the xz-plane) const int maxTessellationLevel = 64; const int trianglesPerHeightSample = 3; const int xDivisions = trianglesPerHeightSample * heightMapSize.width() / maxTessellationLevel; const int zDivisions = trianglesPerHeightSample * heightMapSize.height() / maxTessellationLevel; m_patchCount = xDivisions * zDivisions; QVector<float> positionData( 2 * m_patchCount ); // 2 floats per vertex qDebug() << "Total number of patches =" << m_patchCount; const float dx = 1.0f / static_cast<float>( xDivisions ); const float dz = 1.0f / static_cast<float>( zDivisions ); for ( int j = 0; j < 2 * zDivisions; j += 2 ) { float z = static_cast<float>( j ) * dz * 0.5; for ( int i = 0; i < 2 * xDivisions; i += 2 ) { float x = static_cast<float>( i ) * dx * 0.5; const int index = xDivisions * j + i; positionData[index] = x; positionData[index + 1] = z; } } m_patchBuffer.create(); m_patchBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw ); m_patchBuffer.bind(); m_patchBuffer.allocate( positionData.data(), positionData.size() * sizeof( float ) ); m_patchBuffer.release(); }
void WaterChunk::initialize() { /// Create a Vertex Buffers const int maxTessellationLevel = 64; const int trianglesPerHeightSample = 10; const int xDivisions = trianglesPerHeightSample * TILE_WIDTH / CHUNKS / maxTessellationLevel; const int zDivisions = trianglesPerHeightSample * TILE_HEIGHT / CHUNKS / maxTessellationLevel; int patchCount = xDivisions * zDivisions; QVector<float> positionData(2 * patchCount); // 2 floats per vertex qDebug() << QObject::tr("Total number of patches for waterchunk =") << patchCount; const float dx = 1.0f / MathHelper::toFloat(xDivisions); const float dz = 1.0f / MathHelper::toFloat(zDivisions); for(int j = 0; j < 2 * zDivisions; j += 2) { float z = MathHelper::toFloat(j) * dz * 0.5; for(int i = 0; i < 2 * xDivisions; i += 2) { float x = MathHelper::toFloat(i) * dx * 0.5; const int index = xDivisions * j + i; positionData[index] = x; positionData[index + 1] = z; } } mesh.createVertexArrayObject(); mesh.createBuffer(Mesh::Vertices, positionData.data(), positionData.size() * sizeof(float)); mesh.setNumFaces(patchCount); }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); glfwSwapInterval(0); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code // the vertex shader simply passes through data std::string vertex_source = "#version 430\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the geometry shader creates the billboard quads std::string geometry_source = "#version 430\n" "layout(location = 0) uniform mat4 View;\n" "layout(location = 1) uniform mat4 Projection;\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices = 4) out;\n" "out vec2 txcoord;\n" "void main() {\n" " vec4 pos = View*gl_in[0].gl_Position;\n" " txcoord = vec2(-1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2(-1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" "}\n"; // the fragment shader creates a bell like radial color distribution std::string fragment_source = "#version 330\n" "in vec2 txcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " float s = (1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" " FragColor = s*vec4(0.3,0.3,1.0,1);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler geometry shader geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); source = geometry_source.c_str(); length = geometry_source.size(); glShaderSource(geometry_shader, 1, &source, &length); glCompileShader(geometry_shader); if(!check_shader_compile_status(geometry_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, geometry_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); std::string acceleration_source = "#version 430\n" "layout(local_size_x=256) in;\n" "layout(location = 0) uniform float dt;\n" "layout(rgba32f, location = 1) uniform imageBuffer positions;\n" "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n" "void main() {\n" " int N = int(gl_NumWorkGroups.x*gl_WorkGroupSize.x);\n" " int index = int(gl_GlobalInvocationID);\n" " vec3 position = imageLoad(positions, index).xyz;\n" " vec3 velocity = imageLoad(velocities, index).xyz;\n" " vec3 acceleration = vec3(0,0,0);\n" " for(int i = 0;i<N;++i) {\n" " vec3 other = imageLoad(positions, i).xyz;\n" " vec3 diff = position - other;\n" " float dist = length(diff)+0.001;\n" " acceleration -= 0.1*diff/(dist*dist*dist);\n" " }\n" " imageStore(velocities, index, vec4(velocity+dt*acceleration,0));\n" "}\n"; // program and shader handles GLuint acceleration_program, acceleration_shader; // create and compiler vertex shader acceleration_shader = glCreateShader(GL_COMPUTE_SHADER); source = acceleration_source.c_str(); length = acceleration_source.size(); glShaderSource(acceleration_shader, 1, &source, &length); glCompileShader(acceleration_shader); if(!check_shader_compile_status(acceleration_shader)) { return 1; } // create program acceleration_program = glCreateProgram(); // attach shaders glAttachShader(acceleration_program, acceleration_shader); // link the program and check for errors glLinkProgram(acceleration_program); check_program_link_status(acceleration_program); std::string tiled_acceleration_source = "#version 430\n" "layout(local_size_x=256) in;\n" "layout(location = 0) uniform float dt;\n" "layout(rgba32f, location = 1) uniform imageBuffer positions;\n" "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n" "layout(location = 3) uniform int tile;\n" "shared vec4 tmp[256];\n" "void main() {\n" " int index = int(gl_GlobalInvocationID);\n" " vec3 position = imageLoad(positions, index).xyz;\n" " vec3 velocity = imageLoad(velocities, index).xyz;\n" " vec3 acceleration = vec3(0,0,0);\n" " tmp[gl_LocalInvocationIndex] = imageLoad(positions, 256*tile + int(gl_LocalInvocationIndex));\n" " groupMemoryBarrier();\n" " barrier();\n" " for(int i = 0;i<gl_WorkGroupSize.x;++i) {\n" " vec3 other = tmp[i].xyz;\n" " vec3 diff = position - other;\n" " float invdist = 1/sqrt(dot(diff,diff)+0.00001);\n" " acceleration -= diff*0.1*invdist*invdist*invdist;\n" " }\n" " imageStore(velocities, index, vec4(velocity+dt*acceleration,0));\n" "}\n"; // program and shader handles GLuint tiled_acceleration_program, tiled_acceleration_shader; // create and compiler vertex shader tiled_acceleration_shader = glCreateShader(GL_COMPUTE_SHADER); source = tiled_acceleration_source.c_str(); length = tiled_acceleration_source.size(); glShaderSource(tiled_acceleration_shader, 1, &source, &length); glCompileShader(tiled_acceleration_shader); if(!check_shader_compile_status(tiled_acceleration_shader)) { return 1; } // create program tiled_acceleration_program = glCreateProgram(); // attach shaders glAttachShader(tiled_acceleration_program, tiled_acceleration_shader); // link the program and check for errors glLinkProgram(tiled_acceleration_program); check_program_link_status(tiled_acceleration_program); std::string integrate_source = "#version 430\n" "layout(local_size_x=256) in;\n" "layout(location = 0) uniform float dt;\n" "layout(rgba32f, location = 1) uniform imageBuffer positions;\n" "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n" "void main() {\n" " int index = int(gl_GlobalInvocationID);\n" " vec4 position = imageLoad(positions, index);\n" " vec4 velocity = imageLoad(velocities, index);\n" " position.xyz += dt*velocity.xyz;\n" " imageStore(positions, index, position);\n" "}\n"; // program and shader handles GLuint integrate_program, integrate_shader; // create and compiler vertex shader integrate_shader = glCreateShader(GL_COMPUTE_SHADER); source = integrate_source.c_str(); length = integrate_source.size(); glShaderSource(integrate_shader, 1, &source, &length); glCompileShader(integrate_shader); if(!check_shader_compile_status(integrate_shader)) { return 1; } // create program integrate_program = glCreateProgram(); // attach shaders glAttachShader(integrate_program, integrate_shader); // link the program and check for errors glLinkProgram(integrate_program); check_program_link_status(integrate_program); const int particles = 32*1024; // randomly place particles in a cube std::vector<glm::vec4> positionData(particles); std::vector<glm::vec4> velocityData(particles); for(int i = 0;i<particles;++i) { // initial position positionData[i] = glm::vec4( 1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX), 1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX), 1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX), 0 ); positionData[i] = glm::vec4(0.0f,0.0f,0.0f,1) + glm::vec4(4.0f,1.0f,4.0f,1)*positionData[i]; velocityData[i] = 40.0f*glm::vec4(glm::cross(glm::vec3(positionData[i].xyz()), glm::vec3(0,1,0)), 0)/glm::dot(glm::vec3(positionData[i].xyz()),glm::vec3(positionData[i].xyz())); } // generate positions_vbos and vaos GLuint vao, positions_vbo, velocities_vbo; glGenVertexArrays(1, &vao); glGenBuffers(1, &positions_vbo); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, positions_vbo); // fill with initial data glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4)*particles, &positionData[0], GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // "unbind" vao glBindVertexArray(0); glm::vec4 zero(0,0,0,0); glGenBuffers(1, &velocities_vbo); glBindBuffer(GL_TEXTURE_BUFFER, velocities_vbo); glBufferData(GL_TEXTURE_BUFFER, sizeof(glm::vec4)*particles, &velocityData[0], GL_STATIC_DRAW); // texture handle GLuint positions_texture, velocities_texture; glGenTextures(1, &positions_texture); glBindTexture(GL_TEXTURE_BUFFER, positions_texture); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, positions_vbo); glGenTextures(1, &velocities_texture); glBindTexture(GL_TEXTURE_BUFFER, velocities_texture); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, velocities_vbo); // bind images glBindImageTexture(0, positions_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); glBindImageTexture(1, velocities_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); // physical parameters float dt = 1.0f/60.0f; // setup uniforms glUseProgram(tiled_acceleration_program); glUniform1f(0, dt); glUniform1i(1, 0); glUniform1i(2, 1); glUseProgram(acceleration_program); glUniform1f(0, dt); glUniform1i(1, 0); glUniform1i(2, 1); glUseProgram(integrate_program); glUniform1f(0, dt); glUniform1i(1, 0); glUniform1i(2, 1); // we are blending so no depth testing glDisable(GL_DEPTH_TEST); // enable blending glEnable(GL_BLEND); // and set the blend function to result = 1*source + 1*destination glBlendFunc(GL_ONE, GL_ONE); GLuint query; glGenQueries(1, &query); bool tiled = false; bool space_down = false; running = true; while(running) { // get the time in seconds float t = glfwGetTime(); // terminate on excape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // toggle occlusion culling if(glfwGetKey(GLFW_KEY_SPACE) && !space_down) { tiled = !tiled; } space_down = glfwGetKey(GLFW_KEY_SPACE); glBeginQuery(GL_TIME_ELAPSED, query); if(tiled) { glUseProgram(tiled_acceleration_program); int tiles = particles/256; for(int tile = 0;tile<tiles;++tile) { glUniform1i(3, tile); glDispatchCompute(particles/256, 1, 1); } } else { glUseProgram(acceleration_program); glDispatchCompute(particles/256, 1, 1); } glEndQuery(GL_TIME_ELAPSED); glUseProgram(integrate_program); glDispatchCompute(particles/256, 1, 1); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)); // tilt the camera View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); // set the uniforms glUniformMatrix4fv(0, 1, GL_FALSE, glm::value_ptr(View)); glUniformMatrix4fv(1, 1, GL_FALSE, glm::value_ptr(Projection)); // bind the current vao glBindVertexArray(vao); // draw glDrawArrays(GL_POINTS, 0, particles); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); { GLuint64 result; glGetQueryObjectui64v(query, GL_QUERY_RESULT, &result); std::cout << result*1.e-6 << " ms/frame" << std::endl; } } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &positions_vbo); glDeleteBuffers(1, &velocities_vbo); glDeleteTextures(1, &positions_texture); glDeleteTextures(1, &velocities_texture); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, geometry_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(geometry_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glDetachShader(acceleration_program, acceleration_shader); glDeleteShader(acceleration_shader); glDeleteProgram(acceleration_program); glfwCloseWindow(); glfwTerminate(); return 0; }