void PointsRenderer::updateVaoAndVbo(const Cloud::Key &key, const std::shared_ptr<Cloud> &cloud) { auto points = cloud->point_cloud()->points; set_size(key, points.size()); vbo(key)->copyData(points.size() * sizeof(Cloud::PointT), points.data()); cinder::gl::ScopedVao svao(vao(key)); cinder::gl::ScopedBuffer svbo(vbo(key)); cinder::gl::enableVertexAttribArray(0); cinder::gl::enableVertexAttribArray(1); cinder::gl::vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Cloud::PointT), (const GLvoid*)offsetof(Cloud::PointT, data)); cinder::gl::vertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Cloud::PointT), (const GLvoid*)offsetof(Cloud::PointT, rgba)); }
sf::VertexArray Tilemap::buildVertexArray(const sf::IntRect& rect) const { sf::VertexArray vbo(sf::Quads, rect.width * rect.height * 4); // Amount of tiles * vertice per square for(int x = rect.left, xl = 0; x < std::min(static_cast<int>(wid), rect.left + rect.width); ++x, ++xl) for(int y = rect.top, yl = 0; y < std::min(static_cast<int>(hei), rect.top + rect.height); ++y, ++yl) { const unsigned int vloc = (xl + (yl * rect.width)) * 4, // VBO location rloc = (x + (y * wid)); // Tileset location if (tiles[rloc] != -1) // air { vbo[vloc].position = sf::Vector2f(x * tilesize, y * tilesize); vbo[vloc + 1].position = sf::Vector2f((x + 1) * tilesize, y * tilesize); vbo[vloc + 2].position = sf::Vector2f((x + 1) * tilesize, (y + 1) * tilesize); vbo[vloc + 3].position = sf::Vector2f(x * tilesize, (y + 1) * tilesize); const sf::FloatRect texrect = metatexture.getTexRect(tiles[rloc]); vbo[vloc].texCoords = sf::Vector2f(texrect.left, texrect.top); vbo[vloc + 1].texCoords = sf::Vector2f(texrect.left + texrect.width, texrect.top); vbo[vloc + 2].texCoords = sf::Vector2f(texrect.left + texrect.width, texrect.top + texrect.height); vbo[vloc + 3].texCoords = sf::Vector2f(texrect.left, texrect.top + texrect.height); } } return vbo; }
Geometry::Geometry() : pose_(Eigen::Matrix4f::Identity()), material_(0.5f, 0.0f, 0.5f) { mesh_ = pastry::single_mesh(GL_TRIANGLES); pastry::array_buffer vbo( { {"pos", GL_FLOAT, 3}, {"uv", GL_FLOAT, 2}, {"normal", GL_FLOAT, 3} }, GL_STATIC_DRAW ); mesh_.set_vertex_bo(vbo); sp_ = pastry::load_program("assets/deferred/render"); va_ = pastry::vertex_array(sp_, { {"position", vbo, "pos"}, {"texcoord", vbo, "uv"}, {"normal", vbo, "normal"} }); va_.bind(); }
unique_ptr<RenderableObject> RenderableObject::quad(int startX, int startY, int width, int height, const glm::vec4 &color, GLenum primitive) { glm::vec3 mi(startX, startY, 0.0f); glm::vec3 ma(startX + width, startY + height, 0.0f); vector<glm::vec3> vertices; vector<glm::vec3> normals; vector<glm::vec3> texCoords; float d = 0.1; vertices.push_back(glm::vec3(mi.x, mi.y, d)); vertices.push_back(glm::vec3(mi.x, ma.y, d)); vertices.push_back(glm::vec3(ma.x, ma.y, d)); vertices.push_back(glm::vec3(ma.x, mi.y, d)); normals.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); texCoords.push_back(glm::vec3(0.0f, 0.0f, 0.0f)); texCoords.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); texCoords.push_back(glm::vec3(1.0f, 1.0f, 0.0f)); texCoords.push_back(glm::vec3(1.0f, 0.0f, 0.0f)); // Indices vector<GLuint> indices ={ 0, 1, 2, 0, 2, 3 }; uint nrVertices = vertices.size(); vector<RenderableObject::Vertex> attrData(nrVertices); for(uint i=0; i<nrVertices; ++i) { glm::vec3 v = vertices[i]; glm::vec3 n = normals[i]; glm::vec3 t = texCoords[i]; attrData[i].Position = v; attrData[i].Normal = n; attrData[i].Color = color; attrData[i].TexCoords = glm::vec4(t.x, t.y, 0.0f, 0.0f); } unique_ptr<RenderableObject> vbo(new RenderableObject); vbo->setData(attrData, indices, primitive); return vbo; }
shared_ptr<TexturedMesh> GeometryFactory::createBoundingBox() { // vertex array shared_ptr<BufferedVertexData> vbo(new BufferedVertexData(sizeof(Vec3) * 8, sizeof(Vec3), GL_STATIC_DRAW, GL_ARRAY_BUFFER, nullptr)); vbo->setAttribute("in_position", VertexData::AttribProps(0, 3, GL_FLOAT)); Vec3 * vertex_array = (Vec3 *)vbo->mapData(); float half_x = 1 / 2.0; float half_y = 1 / 2.0; float half_z = 1 / 2.0; vertex_array[0] = Vec3(-half_x, -half_y, half_z); vertex_array[1] = Vec3( half_x, -half_y, half_z); vertex_array[2] = Vec3( half_x, -half_y, -half_z); vertex_array[3] = Vec3(-half_x, -half_y, -half_z); vertex_array[4] = Vec3(-half_x, half_y, half_z); vertex_array[5] = Vec3( half_x, half_y, half_z); vertex_array[6] = Vec3( half_x, half_y, -half_z); vertex_array[7] = Vec3(-half_x, half_y, -half_z); vbo->unmapData(); // indices shared_ptr<BufferedVertexData> ibo(new BufferedVertexData(sizeof(unsigned short) * 16, sizeof(unsigned short), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER, nullptr)); unsigned short * indices = (unsigned short*)ibo->mapData(); indices[0] = 4; indices[1] = 0; indices[2] = 1; indices[3] = 5; indices[4] = 6; indices[5] = 2; indices[6] = 3; indices[7] = 7; indices[8] = 4; indices[9] = 5; indices[10] = 1; indices[11] = 2; indices[12] = 6; indices[13] = 7; indices[14] = 3; indices[15] = 0; ibo->unmapData(); return shared_ptr<TexturedMesh>(new TexturedMesh(ibo, vbo, GL_LINE_STRIP, 16)); }
shared_ptr<TexturedMesh> GeometryFactory::createPlane() { float width = 1; float height = 1; int subdivs = 30; float offsetX = 1.0 / subdivs; float offsetZ = 1.0 / subdivs; unsigned size = subdivs * (4 + subdivs * 2) * sizeof(Vec3) * 3; shared_ptr<BufferedVertexData> vbo(new BufferedVertexData(size, sizeof(Vec3) * 3, GL_STATIC_DRAW, GL_ARRAY_BUFFER, nullptr)); vbo->setAttribute("in_position", VertexData::AttribProps(0, 3, GL_FLOAT)); vbo->setAttribute("in_normal", VertexData::AttribProps(sizeof(Vec3), 3, GL_FLOAT)); vbo->setAttribute("in_texcoord", VertexData::AttribProps(sizeof(Vec3) * 2, 2, GL_FLOAT)); Vec3 * vbo_array = (Vec3 *)vbo->mapData(); int idx = 0; for (int j = 1; j <= subdivs; j++) { vbo_array[idx++] = Vec3((offsetX * (j - 1) - 0.5) * width, 0, - 0.5 * height); // vertex vbo_array[idx++] = Vec3(0, 1, 0); // normal vbo_array[idx++] = Vec3(offsetX * (j - 1), 0.0, 0); // texture coordinate vbo_array[idx++] = Vec3((offsetX * j - 0.5) * width, 0, - 0.5 * height); vbo_array[idx++] = Vec3(0, 1, 0); vbo_array[idx++] = Vec3(offsetX * j, 0.0, 0); for (int i = 1; i <= subdivs; i++) { vbo_array[idx++] = Vec3((offsetX * (j - 1) - 0.5) * width, 0, (offsetZ * i - 0.5) * height); vbo_array[idx++] = Vec3(0, 1, 0); vbo_array[idx++] = Vec3(offsetX * (j - 1), offsetZ * i, 0); vbo_array[idx++] = Vec3((offsetX * j - 0.5) * width, 0, (offsetZ * i - 0.5) * height); vbo_array[idx++] = Vec3(0, 1, 0); vbo_array[idx++] = Vec3(offsetX * j, offsetZ * i, 0); } vbo_array[idx++] = Vec3((offsetX * j - 0.5) * width, 0, (offsetZ * subdivs - 0.5) * height); vbo_array[idx++] = Vec3(0, 1, 0); vbo_array[idx++] = Vec3(offsetX * j - 1.0, offsetX * subdivs, 0); vbo_array[idx++] = Vec3((offsetX * j - 0.5) * width, 0, - 0.5 * height); vbo_array[idx++] = Vec3(0, 1, 0); vbo_array[idx++] = Vec3(offsetX * j, 0.0, 0); } vbo->unmapData(); return shared_ptr<TexturedMesh>(new TexturedMesh(nullptr, vbo, GL_TRIANGLE_STRIP, idx/3)); }
shared_ptr<TexturedMesh> GeometryFactory::createBox() { shared_ptr<BufferedVertexData> vbo(new BufferedVertexData(216 * sizeof(float), sizeof(float) * 6, GL_STATIC_DRAW, GL_ARRAY_BUFFER, nullptr)); vbo->setAttribute("in_position", VertexData::AttribProps(0, 3, GL_FLOAT)); vbo->setAttribute("in_normal", VertexData::AttribProps(sizeof(float) * 3, 3, GL_FLOAT)); float * vertex_array = (float *)vbo->mapData(); memcpy(vertex_array, CubeVertexData, sizeof(float)*216); vbo->unmapData(); return shared_ptr<TexturedMesh>(new TexturedMesh(nullptr, vbo, GL_TRIANGLES, 36)); }
osg::ref_ptr<osg::Node> MeshManager::getTerrain(int size) { auto iter = mTerrainCache.find(size); if(iter != mTerrainCache.end()) { osg::ref_ptr<osg::Node> node; if(iter->second.lock(node)) return node; } if(!mTerrainProgram) { mTerrainProgram = new osg::Program(); mTerrainProgram->addShader(osgDB::readShaderFile(osg::Shader::VERTEX, "shaders/terrain.vert")); mTerrainProgram->addShader(osgDB::readShaderFile(osg::Shader::FRAGMENT, "shaders/terrain.frag")); } osg::ref_ptr<osg::Vec3Array> vtxs(new osg::Vec3Array(4)); (*vtxs)[0] = osg::Vec3( 0.0f, 0.0f, 0.0f); (*vtxs)[1] = osg::Vec3( 0.0f, 0.0f, -256.0f); (*vtxs)[2] = osg::Vec3(256.0f, 0.0f, -256.0f); (*vtxs)[3] = osg::Vec3(256.0f, 0.0f, 0.0f); osg::ref_ptr<osg::Vec2Array> texcrds(new osg::Vec2Array(4)); (*texcrds)[0] = osg::Vec2(0.0f, 0.0f); (*texcrds)[1] = osg::Vec2(0.0f, 1.0f); (*texcrds)[2] = osg::Vec2(1.0f, 1.0f); (*texcrds)[3] = osg::Vec2(1.0f, 0.0f); osg::ref_ptr<osg::VertexBufferObject> vbo(new osg::VertexBufferObject()); vtxs->setVertexBufferObject(vbo); texcrds->setVertexBufferObject(vbo); osg::ref_ptr<osg::Geometry> geometry(new osg::Geometry); geometry->setVertexArray(vtxs); geometry->setTexCoordArray(0, texcrds, osg::Array::BIND_PER_VERTEX); geometry->setUseDisplayList(false); geometry->setUseVertexBufferObjects(true); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vtxs->size(), size*size)); geometry->setInitialBound(osg::BoundingBox(osg::Vec3(0.0f, -0.5f, -256.0f*size), osg::Vec3(256.0f*size, 0.5f, 0.0f))); osg::StateSet *ss = geometry->getOrCreateStateSet(); ss->setAttributeAndModes(mTerrainProgram); ss->addUniform(new osg::Uniform("diffuseTex", 0)); ss->addUniform(new osg::Uniform("tilemapTex", 1)); osg::ref_ptr<osg::Geode> base(new osg::Geode()); base->addDrawable(geometry); mTerrainCache[size] = osg::ref_ptr<osg::Node>(base); return base; }
void VertexAttributeBindingImplementation_Legacy::finish(const VertexAttributeBinding * binding) const { assert(bindingData(binding) != nullptr); vao(binding)->bind(); void * offset = nullptr; if (vbo(binding)) { vbo(binding)->bind(GL_ARRAY_BUFFER); const auto offset64 = static_cast<GLuint64>(bindingData(binding)->baseoffset + bindingData(binding)->format.relativeoffset); offset = reinterpret_cast<void *>(offset64); } else { Buffer::unbind(GL_ARRAY_BUFFER); } const GLint attribute = attributeIndex(binding); switch (bindingData(binding)->format.method) { case Format::Method::I: glVertexAttribIPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type , bindingData(binding)->stride, offset); break; case Format::Method::L: glVertexAttribLPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type , bindingData(binding)->stride, offset); break; default: glVertexAttribPointer(attribute, bindingData(binding)->format.size, bindingData(binding)->format.type , bindingData(binding)->format.normalized, bindingData(binding)->stride, offset); } }
void NetworkAccessTest::testCase1() { #ifdef USE_CUDA QVERIFY( cudaSuccess == cudaGLSetGLDevice( 0 ) ); #ifndef __APPLE__ // glewInit is not needed on Mac QVERIFY( 0==glewInit() ); #endif pVbo vbo( new Vbo(1024, GL_ARRAY_BUFFER, GL_STATIC_DRAW)); MappedVbo<float> mapping(vbo, DataStorageSize(256,1,1)); DataStorage<float>::ptr copy( new DataStorage<float>(*mapping.data) ); mappedVboTestCuda( copy ); QVERIFY2(true, "Failure"); #endif }
void RigGeometry::setSourceGeometry(osg::ref_ptr<osg::Geometry> sourceGeometry) { mSourceGeometry = sourceGeometry; for (unsigned int i=0; i<2; ++i) { const osg::Geometry& from = *sourceGeometry; mGeometry[i] = new osg::Geometry(from, osg::CopyOp::SHALLOW_COPY); osg::Geometry& to = *mGeometry[i]; to.setSupportsDisplayList(false); to.setUseVertexBufferObjects(true); to.setCullingActive(false); // make sure to disable culling since that's handled by this class to.setComputeBoundingBoxCallback(new CopyBoundingBoxCallback()); to.setComputeBoundingSphereCallback(new CopyBoundingSphereCallback()); // vertices and normals are modified every frame, so we need to deep copy them. // assign a dedicated VBO to make sure that modifications don't interfere with source geometry's VBO. osg::ref_ptr<osg::VertexBufferObject> vbo (new osg::VertexBufferObject); vbo->setUsage(GL_DYNAMIC_DRAW_ARB); osg::ref_ptr<osg::Array> vertexArray = osg::clone(from.getVertexArray(), osg::CopyOp::DEEP_COPY_ALL); if (vertexArray) { vertexArray->setVertexBufferObject(vbo); to.setVertexArray(vertexArray); } if (const osg::Array* normals = from.getNormalArray()) { osg::ref_ptr<osg::Array> normalArray = osg::clone(normals, osg::CopyOp::DEEP_COPY_ALL); if (normalArray) { normalArray->setVertexBufferObject(vbo); to.setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX); } } if (const osg::Vec4Array* tangents = dynamic_cast<const osg::Vec4Array*>(from.getTexCoordArray(7))) { mSourceTangents = tangents; osg::ref_ptr<osg::Array> tangentArray = osg::clone(tangents, osg::CopyOp::DEEP_COPY_ALL); tangentArray->setVertexBufferObject(vbo); to.setTexCoordArray(7, tangentArray, osg::Array::BIND_PER_VERTEX); } else mSourceTangents = nullptr; } }
unique_ptr<RenderableObject> RenderableObject::sphere(float radius, int iterations, const glm::vec4 &color, GLenum primitive) { vector<FACET3> f((int)pow(4.0, iterations)); int n = CreateUnitSphere(f, iterations); vector<glm::vec3> vertices; vector<glm::vec3> normals; for(int i=0; i<n; ++i) { FACET3& facet = f[i]; vertices.push_back(facet.p1 * radius); vertices.push_back(facet.p2 * radius); vertices.push_back(facet.p3 * radius); facet.p1 = glm::normalize(facet.p1); facet.p2 = glm::normalize(facet.p2); facet.p3 = glm::normalize(facet.p3); normals.push_back(facet.p1); normals.push_back(facet.p2); normals.push_back(facet.p3); } uint nrVertices = vertices.size(); vector<RenderableObject::Vertex> attrData(nrVertices); for(uint i=0; i<nrVertices; ++i) { glm::vec3 v = vertices[i]; glm::vec3 n = normals[i]; attrData[i].Position = v; attrData[i].Normal = n; attrData[i].Color = color; } unique_ptr<RenderableObject> vbo(new RenderableObject); vbo->setData(attrData, primitive); return vbo; }
unique_ptr<RenderableObject> RenderableObject::quadLines(int startX, int startY, int width, int height, const glm::vec4 &color) { glm::vec3 mi(startX, startY, 0.0f); glm::vec3 ma(startX + width, startY + height, 0.0f); vector<glm::vec3> vertices; vector<glm::vec3> normals; float d = 0.1; vertices.push_back(glm::vec3(mi.x, mi.y, d)); vertices.push_back(glm::vec3(mi.x, ma.y, d)); vertices.push_back(glm::vec3(mi.x, ma.y, d)); vertices.push_back(glm::vec3(ma.x, ma.y, d)); vertices.push_back(glm::vec3(ma.x, ma.y, d)); vertices.push_back(glm::vec3(ma.x, mi.y, d)); vertices.push_back(glm::vec3(ma.x, mi.y, d)); vertices.push_back(glm::vec3(mi.x, mi.y, d)); uint nrVertices = vertices.size(); vector<RenderableObject::Vertex> attrData(nrVertices); for(uint i=0; i<nrVertices; ++i) { glm::vec3 v = vertices[i]; attrData[i].Position = v; attrData[i].Color = color; } unique_ptr<RenderableObject> vbo(new RenderableObject); vbo->setData(attrData, GL_LINES); return vbo; }
int main() { // Setup SDL wrapper sdl::set_error_callback([](const std::string &err) { std::cout << err << std::endl; }); sdl::window window(width, height, false, "Test Renderer"); sdl::ogl_context context(window); // Setup Simple Renderer renderer::set_log_callback([](const uint32_t id, const std::string &err) { std::cout << id << " : " << std::endl; }); renderer::initialize(); renderer::clear_color(0.4f, 0.2f, 0.2f); // Load assets and shader const auto resource_path = util::get_resource_path() + "assets/"; const std::vector<std::string> models = { "test_scene.obj", }; std::vector<renderer::vertex_buffer> buffers; for(const auto &m : models) { const auto model = util::load_obj(resource_path + m); // Load meshes for(const auto &mesh : model.meshes) { const auto gl_model = util::convert_to_open_gl_mesh(mesh); renderer::vertex_buffer vbo(gl_model.mesh_data); buffers.emplace_back(std::move(vbo)); assert(buffers.back().is_valid()); } } // Shaders const std::string fullbright_shader_code_raw = util::get_contents_from_file(resource_path + "fullbright.shd"); const std::string fullbright_shader_code_preprocessed = util::hash_include_string(fullbright_shader_code_raw, {resource_path}); const auto fullbright_shd_code = renderer::shader_utils::get_shader_code_from_tagged_string(fullbright_shader_code_preprocessed); renderer::shader fullbright_shader(fullbright_shd_code.vs_code, "", fullbright_shd_code.ps_code); assert(fullbright_shader.is_valid()); const std::string forward_shader_code_raw = util::get_contents_from_file(resource_path + "forward_lighting.shd"); const std::string forward_shader_code_preprocessed = util::hash_include_string(forward_shader_code_raw, {resource_path}); const auto forward_shd_code = renderer::shader_utils::get_shader_code_from_tagged_string(forward_shader_code_preprocessed); renderer::shader forward_shader(forward_shd_code.vs_code, "", forward_shd_code.ps_code); assert(forward_shader.is_valid()); const std::string shadow_sahder_code_raw = util::get_contents_from_file(resource_path + "shadow_map.shd"); const std::string shadow_sahder_code_preprocessed = util::hash_include_string(shadow_sahder_code_raw, {resource_path}); const auto shadow_map_shd_code = renderer::shader_utils::get_shader_code_from_tagged_string(shadow_sahder_code_preprocessed); renderer::shader shadow_shader(shadow_map_shd_code.vs_code, "", shadow_map_shd_code.ps_code); assert(shadow_shader.is_valid()); const std::vector<renderer::attr_format_desc> vertex_desc = { renderer::attr_format_desc{"in_vs_position", renderer::attr_type::FLOAT3}, renderer::attr_format_desc{"in_vs_texcoord", renderer::attr_type::FLOAT2}, renderer::attr_format_desc{"in_vs_normal", renderer::attr_type::FLOAT3}, }; renderer::vertex_format vert_fmt(vertex_desc); assert(vert_fmt.is_valid()); // Texture int32_t width = 0; int32_t height = 0; const auto file_path = resource_path + "test.png"; unsigned char *image0 = SOIL_load_image(file_path.c_str(), &width, &height, 0, SOIL_LOAD_RGBA); renderer::texture test_texture0(image0, width, height); assert(test_texture0.is_valid()); SOIL_free_image_data(image0); Light_utils::create_direction_light(&lights); Light_utils::create_random_point_lights_inside_range(&lights, 5, 5); // Shadow cube map GLuint m_fbo; GLuint m_shadowMap; GLuint m_depth; const uint32_t cube_size = 2048; // Create the FBO glGenFramebuffers(1, &m_fbo); // Create the depth buffer glGenTextures(1, &m_depth); glBindTexture(GL_TEXTURE_2D, m_depth); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, cube_size, cube_size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); // Create the cube map glGenTextures(1, &m_shadowMap); glBindTexture(GL_TEXTURE_CUBE_MAP, m_shadowMap); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); for (uint i = 0 ; i < 6 ; i++) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_R32F, cube_size, cube_size, 0, GL_RED, GL_FLOAT, NULL); } glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depth, 0); // Disable writes to the color buffer glDrawBuffer(GL_NONE); // Disable reads from the color buffer glReadBuffer(GL_NONE); GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (Status != GL_FRAMEBUFFER_COMPLETE) { printf("FB error, status: 0x%x\n", Status); return false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); // Game loop while(!window.wants_to_quit()) { sdl::message_pump(); const uint32_t NUM_OF_LAYERS = 6; struct Cam_dir { GLint cube; math::vec3 tar; math::vec3 up; }; std::array<Cam_dir, NUM_OF_LAYERS> cam_dirs = { Cam_dir{ GL_TEXTURE_CUBE_MAP_POSITIVE_X, math::vec3_init(1.0f, 0.0f, 0.0f), math::vec3_init(0.0f, -1.0f, 0.0f) }, Cam_dir{ GL_TEXTURE_CUBE_MAP_NEGATIVE_X, math::vec3_init(-1.0f, 0.0f, 0.0f), math::vec3_init(0.0f, -1.0f, 0.0f) }, Cam_dir{ GL_TEXTURE_CUBE_MAP_POSITIVE_Y, math::vec3_init(0.0f, 1.0f, 0.0f), math::vec3_init(0.0f, 0.0f, -1.0f) }, Cam_dir{ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, math::vec3_init(0.0f, -1.0f, 0.0f), math::vec3_init(0.0f, 0.0f, 1.0f) }, Cam_dir{ GL_TEXTURE_CUBE_MAP_POSITIVE_Z, math::vec3_init(0.0f, 0.0f, 1.0f), math::vec3_init(0.0f, -1.0f, 0.0f) }, Cam_dir{ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, math::vec3_init(0.0f, 0.0f, -1.0f), math::vec3_init(0.0f, -1.0f, 0.0f) } }; renderer::clear(); renderer::reset(); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); //glEnable(GL_TEXTURE_CUBE_MAP); // Hack! we just copy them to remove errors from rotation transform static float angle = 0.f; angle += 0.005f; auto copy_lights = lights; Light_utils::rotate_points_around_origin(©_lights, angle); // Shadows { glCullFace(GL_FRONT); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); //glClearColor(1.0, 1.0, 1.0, 1.0); for (uint i = 0 ; i < NUM_OF_LAYERS ; i++) { // Bind FBO? glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cam_dirs.at(i).cube, m_shadowMap, 0); glDrawBuffer(GL_COLOR_ATTACHMENT0); const math::mat4 sh_proj = math::mat4_projection(1, 1, 0.1f, 100.f, math::quart_tau()); const math::mat4 sh_world = math::mat4_id(); const math::vec3 light_pos = math::vec3_init(copy_lights.points[0].position[0], copy_lights.points[0].position[1], copy_lights.points[0].position[2]); const math::vec3 dir = math::vec3_add(light_pos, cam_dirs.at(i).tar); const math::mat4 sh_view = math::mat4_lookat(light_pos, dir, cam_dirs.at(i).up); const math::mat4 sh_wvp = math::mat4_multiply(sh_world, sh_view, sh_proj); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); shadow_shader.set_raw_data("uni_wvp_mat", math::mat4_get_data(sh_wvp), sizeof(float) * 16); shadow_shader.set_raw_data("uni_world_mat", math::mat4_get_data(sh_world), sizeof(float) * 16); shadow_shader.set_raw_data("uni_light_world_pos", ©_lights.points[0].position[0], sizeof(float) * 3); for(const auto &buff : buffers) { shadow_shader.bind(); buff.bind(vert_fmt, shadow_shader); const uint32_t number_of_vertices = buff.get_number_entries() / vert_fmt.get_number_of_entires(); glDrawArrays(GL_TRIANGLES, 0, number_of_vertices); } } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } renderer::reset(); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Lighting renderer::shader &curr_shader = [&]() -> renderer::shader& { if(current_render_path == Render_path::forward_lighting) { const float spec_power = 10.f; const float spec_intensity = 10.f; glUseProgram(forward_shader.get_program_gl_id()); // eek glActiveTexture(GL_TEXTURE0 + 1); glBindTexture(GL_TEXTURE_CUBE_MAP, m_shadowMap); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); forward_shader.set_raw_data("specular_intensity", &spec_power, sizeof(float)); forward_shader.set_raw_data("specular_power", &spec_power, sizeof(float)); forward_shader.set_raw_data("eye_position", &eye_position, sizeof(float) * 3); // For Dir lights for(uint32_t i = 0; i < std::min<uint32_t>(copy_lights.directionals.size(), 0); ++i) { forward_shader.set_raw_data("dir_light[" + std::to_string(i) + "].color", copy_lights.directionals[i].color, sizeof(float) * 3); forward_shader.set_raw_data("dir_light[" + std::to_string(i) + "].direction", copy_lights.directionals[i].direction, sizeof(float) * 3); forward_shader.set_raw_data("dir_light[" + std::to_string(i) + "].ambient", ©_lights.directionals[i].ambient, sizeof(float)); forward_shader.set_raw_data("dir_light[" + std::to_string(i) + "].diffuse", ©_lights.directionals[i].diffuse, sizeof(float)); } // For Point lights for(uint32_t i = 0; i < std::min<uint32_t>(copy_lights.points.size(), 1); ++i) { forward_shader.set_raw_data("point_light[" + std::to_string(i) + "].color", copy_lights.points[i].color, sizeof(float) * 3); forward_shader.set_raw_data("point_light[" + std::to_string(i) + "].position", copy_lights.points[i].position, sizeof(float) * 3); forward_shader.set_raw_data("point_light[" + std::to_string(i) + "].ambient", ©_lights.points[i].ambient, sizeof(float)); forward_shader.set_raw_data("point_light[" + std::to_string(i) + "].diffuse", ©_lights.points[i].diffuse, sizeof(float)); forward_shader.set_raw_data("point_light[" + std::to_string(i) + "].atten.constant", ©_lights.points[i].atten_constant, sizeof(float)); forward_shader.set_raw_data("point_light[" + std::to_string(i) + "].atten.linear", ©_lights.points[i].atten_linear, sizeof(float)); forward_shader.set_raw_data("point_light[" + std::to_string(i) + "].atten.expon", ©_lights.points[i].atten_expon, sizeof(float)); } return forward_shader; } return fullbright_shader; }(); // functional burger! for(const auto &buff : buffers) { const math::vec3 light_pos = math::vec3_init(copy_lights.points[0].position[0], copy_lights.points[0].position[1], copy_lights.points[0].position[2]); const math::vec3 dir = math::vec3_add(light_pos, cam_dirs.at(0).tar); auto test_view = math::mat4_lookat(light_pos, dir, cam_dirs.at(0).up); curr_shader.set_raw_data("view", math::mat4_get_data(view), sizeof(float) * 16); curr_shader.set_raw_data("proj", math::mat4_get_data(proj), sizeof(float) * 16); curr_shader.set_raw_data("model", math::mat4_get_data(world), sizeof(float) * 16); curr_shader.set_texture("diffuse_map", test_texture0); renderer::draw(curr_shader, vert_fmt, buff); } window.flip_buffer(); } return 0; }
osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter) { if (chunkSize * mNumSplits > 1.f) { // keep splitting osg::ref_ptr<osg::Group> group (new osg::Group); if (parent) parent->addChild(group); float newChunkSize = chunkSize/2.f; buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, newChunkSize/2.f)); buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, -newChunkSize/2.f)); buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize/2.f, newChunkSize/2.f)); buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize/2.f, -newChunkSize/2.f)); return group; } else { float minH, maxH; if (!mStorage->getMinMaxHeights(chunkSize, chunkCenter, minH, maxH)) return NULL; // no terrain defined osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize(); osg::ref_ptr<SceneUtil::PositionAttitudeTransform> transform (new SceneUtil::PositionAttitudeTransform); transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f)); if (parent) parent->addChild(transform); osg::ref_ptr<osg::Vec3Array> positions (new osg::Vec3Array); osg::ref_ptr<osg::Vec3Array> normals (new osg::Vec3Array); osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array); osg::ref_ptr<osg::VertexBufferObject> vbo (new osg::VertexBufferObject); positions->setVertexBufferObject(vbo); normals->setVertexBufferObject(vbo); colors->setVertexBufferObject(vbo); mStorage->fillVertexBuffers(0, chunkSize, chunkCenter, positions, normals, colors); osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry); geometry->setVertexArray(positions); geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX); geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); geometry->setUseDisplayList(false); geometry->setUseVertexBufferObjects(true); geometry->addPrimitiveSet(mCache.getIndexBuffer(0)); // we already know the bounding box, so no need to let OSG compute it. osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize, -0.5f*mStorage->getCellWorldSize()*chunkSize, minH); osg::Vec3f max (0.5f*mStorage->getCellWorldSize()*chunkSize, 0.5f*mStorage->getCellWorldSize()*chunkSize, maxH); osg::BoundingBox bounds(min, max); geometry->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(bounds)); std::vector<LayerInfo> layerList; std::vector<osg::ref_ptr<osg::Image> > blendmaps; mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList); // For compiling textures, I don't think the osgFX::Effect does it correctly osg::ref_ptr<osg::Node> textureCompileDummy (new osg::Node); unsigned int dummyTextureCounter = 0; bool useShaders = mResourceSystem->getSceneManager()->getForceShaders(); if (!mResourceSystem->getSceneManager()->getClampLighting()) useShaders = true; // always use shaders when lighting is unclamped, this is to avoid lighting seams between a terrain chunk with normal maps and one without normal maps std::vector<TextureLayer> layers; { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mTextureCacheMutex); for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it) { TextureLayer textureLayer; textureLayer.mSpecular = it->mSpecular; osg::ref_ptr<osg::Texture2D> texture = mTextureCache[it->mDiffuseMap]; if (!texture) { texture = new osg::Texture2D(mResourceSystem->getImageManager()->getImage(it->mDiffuseMap)); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); mResourceSystem->getSceneManager()->applyFilterSettings(texture); mTextureCache[it->mDiffuseMap] = texture; } textureLayer.mDiffuseMap = texture; textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, texture); if (!it->mNormalMap.empty()) { texture = mTextureCache[it->mNormalMap]; if (!texture) { texture = new osg::Texture2D(mResourceSystem->getImageManager()->getImage(it->mNormalMap)); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); mResourceSystem->getSceneManager()->applyFilterSettings(texture); mTextureCache[it->mNormalMap] = texture; } textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, texture); textureLayer.mNormalMap = texture; } if (it->requiresShaders()) useShaders = true; layers.push_back(textureLayer); } } std::vector<osg::ref_ptr<osg::Texture2D> > blendmapTextures; for (std::vector<osg::ref_ptr<osg::Image> >::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it) { osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D); texture->setImage(*it); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); texture->setResizeNonPowerOfTwoHint(false); blendmapTextures.push_back(texture); textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, blendmapTextures.back()); } // use texture coordinates for both texture units, the layer texture and blend texture for (unsigned int i=0; i<2; ++i) geometry->setTexCoordArray(i, mCache.getUVBuffer()); float blendmapScale = ESM::Land::LAND_TEXTURE_SIZE*chunkSize; osg::ref_ptr<osgFX::Effect> effect (new Terrain::Effect(mShaderManager ? useShaders : false, mResourceSystem->getSceneManager()->getForcePerPixelLighting(), mResourceSystem->getSceneManager()->getClampLighting(), mShaderManager, layers, blendmapTextures, blendmapScale, blendmapScale)); effect->addCullCallback(new SceneUtil::LightListCallback); transform->addChild(effect); osg::Node* toAttach = geometry.get(); effect->addChild(toAttach); if (mIncrementalCompileOperation) { mIncrementalCompileOperation->add(toAttach); mIncrementalCompileOperation->add(textureCompileDummy); } return transform; } }
int main( int argc, char* argv[] ) { // Initialise window pangolin::View& container = SetupPangoGLWithCuda(1024, 768); size_t cu_mem_start, cu_mem_end, cu_mem_total; cudaMemGetInfo( &cu_mem_start, &cu_mem_total ); glClearColor(1,1,1,0); // Open video device hal::Camera video = OpenRpgCamera(argc,argv); // Capture first image pb::ImageArray images; // N cameras, each w*h in dimension, greyscale const size_t N = video.NumChannels(); if( N != 2 ) { std::cerr << "Two images are required to run this program!" << std::endl; exit(1); } const size_t nw = video.Width(); const size_t nh = video.Height(); // Capture first image video.Capture(images); // Downsample this image to process less pixels const int max_levels = 6; const int level = roo::GetLevelFromMaxPixels( nw, nh, 640*480 ); // const int level = 4; assert(level <= max_levels); // Find centered image crop which aligns to 16 pixels at given level const NppiRect roi = roo::GetCenteredAlignedRegion(nw,nh,16 << level,16 << level); // Load Camera intrinsics from file GetPot clArgs( argc, argv ); const std::string filename = clArgs.follow("","-cmod"); if( filename.empty() ) { std::cerr << "Camera models file is required!" << std::endl; exit(1); } const calibu::CameraRig rig = calibu::ReadXmlRig(filename); if( rig.cameras.size() != 2 ) { std::cerr << "Two camera models are required to run this program!" << std::endl; exit(1); } Eigen::Matrix3f CamModel0 = rig.cameras[0].camera.K().cast<float>(); Eigen::Matrix3f CamModel1 = rig.cameras[1].camera.K().cast<float>(); roo::ImageIntrinsics camMod[] = { {CamModel0(0,0),CamModel0(1,1),CamModel0(0,2),CamModel0(1,2)}, {CamModel1(0,0),CamModel1(1,1),CamModel1(0,2),CamModel1(1,2)} }; for(int i=0; i<2; ++i ) { // Adjust to match camera image dimensions const double scale = nw / rig.cameras[i].camera.Width(); roo::ImageIntrinsics camModel = camMod[i].Scale( scale ); // Adjust to match cropped aligned image camModel = camModel.CropToROI( roi ); camMod[i] = camModel; } const unsigned int w = roi.width; const unsigned int h = roi.height; const unsigned int lw = w >> level; const unsigned int lh = h >> level; const Eigen::Matrix3d& K0 = camMod[0].Matrix(); const Eigen::Matrix3d& Kl = camMod[0][level].Matrix(); std::cout << "K Matrix: " << std::endl << K0 << std::endl; std::cout << "K Matrix - Level: " << std::endl << Kl << std::endl; std::cout << "Video stream dimensions: " << nw << "x" << nh << std::endl; std::cout << "Chosen Level: " << level << std::endl; std::cout << "Processing dimensions: " << lw << "x" << lh << std::endl; std::cout << "Offset: " << roi.x << "x" << roi.y << std::endl; // print selected camera model std::cout << "Camera Model used: " << std::endl << camMod[0][level].Matrix() << std::endl; Eigen::Matrix3d RDFvision;RDFvision<< 1,0,0, 0,1,0, 0,0,1; Eigen::Matrix3d RDFrobot; RDFrobot << 0,1,0, 0,0, 1, 1,0,0; Eigen::Matrix4d T_vis_ro = Eigen::Matrix4d::Identity(); T_vis_ro.block<3,3>(0,0) = RDFvision.transpose() * RDFrobot; Eigen::Matrix4d T_ro_vis = Eigen::Matrix4d::Identity(); T_ro_vis.block<3,3>(0,0) = RDFrobot.transpose() * RDFvision; const Sophus::SE3d T_rl_orig = T_rlFromCamModelRDF(rig.cameras[0], rig.cameras[1], RDFvision); // TODO(jmf): For now, assume cameras are rectified. Later allow unrectified cameras. /* double k1 = 0; double k2 = 0; if(cam[0].Type() == MVL_CAMERA_WARPED) { k1 = cam[0].GetModel()->warped.kappa1; k2 = cam[0].GetModel()->warped.kappa2; } */ const bool rectify = false; if(!rectify) { std::cout << "Using pre-rectified images" << std::endl; } // Check we received at least two images if(images.Size() < 2) { std::cerr << "Failed to capture first stereo pair from camera" << std::endl; return -1; } // Define Camera Render Object (for view / scene browsing) pangolin::OpenGlRenderState s_cam( pangolin::ProjectionMatrixRDF_TopLeft(w,h,K0(0,0),K0(1,1),K0(0,2),K0(1,2),0.1,10000), pangolin::IdentityMatrix(pangolin::GlModelViewStack) ); pangolin::GlBufferCudaPtr vbo(pangolin::GlArrayBuffer, lw*lh,GL_FLOAT, 4, cudaGraphicsMapFlagsWriteDiscard, GL_STREAM_DRAW ); pangolin::GlBufferCudaPtr cbo(pangolin::GlArrayBuffer, lw*lh,GL_UNSIGNED_BYTE, 4, cudaGraphicsMapFlagsWriteDiscard, GL_STREAM_DRAW ); pangolin::GlBuffer ibo = pangolin::MakeTriangleStripIboForVbo(lw,lh); // Allocate Camera Images on device for processing roo::Image<unsigned char, roo::TargetHost, roo::DontManage> hCamImg[] = {{0,nw,nh},{0,nw,nh}}; roo::Image<float2, roo::TargetDevice, roo::Manage> dLookup[] = {{w,h},{w,h}}; roo::Image<unsigned char, roo::TargetDevice, roo::Manage> upload(w,h); roo::Pyramid<unsigned char, max_levels, roo::TargetDevice, roo::Manage> img_pyr[] = {{w,h},{w,h}}; roo::Image<float, roo::TargetDevice, roo::Manage> img[] = {{lw,lh},{lw,lh}}; roo::Volume<float, roo::TargetDevice, roo::Manage> vol[] = {{lw,lh,MAXD},{lw,lh,MAXD}}; roo::Image<float, roo::TargetDevice, roo::Manage> disp[] = {{lw,lh},{lw,lh}}; roo::Image<float, roo::TargetDevice, roo::Manage> meanI(lw,lh); roo::Image<float, roo::TargetDevice, roo::Manage> varI(lw,lh); roo::Image<float, roo::TargetDevice, roo::Manage> temp[] = {{lw,lh},{lw,lh},{lw,lh},{lw,lh},{lw,lh}}; roo::Image<float,roo::TargetDevice, roo::Manage>& imgd = disp[0]; roo::Image<float,roo::TargetDevice, roo::Manage> depthmap(lw,lh); roo::Image<float,roo::TargetDevice, roo::Manage> imga(lw,lh); roo::Image<float2,roo::TargetDevice, roo::Manage> imgq(lw,lh); roo::Image<float,roo::TargetDevice, roo::Manage> imgw(lw,lh); roo::Image<float4, roo::TargetDevice, roo::Manage> d3d(lw,lh); roo::Image<unsigned char, roo::TargetDevice,roo::Manage> Scratch(lw*sizeof(roo::LeastSquaresSystem<float,6>),lh); typedef ulong4 census_t; roo::Image<census_t, roo::TargetDevice, roo::Manage> census[] = {{lw,lh},{lw,lh}}; // Stereo transformation (post-rectification) Sophus::SE3d T_rl = T_rl_orig; const double baseline = T_rl.translation().norm(); std::cout << "Baseline: " << baseline << std::endl; cudaMemGetInfo( &cu_mem_end, &cu_mem_total ); std::cout << "CuTotal: " << cu_mem_total/(1024*1024) << ", Available: " << cu_mem_end/(1024*1024) << ", Used: " << (cu_mem_start-cu_mem_end)/(1024*1024) << std::endl; pangolin::Var<bool> step("ui.step", false, false); pangolin::Var<bool> run("ui.run", false, true); pangolin::Var<bool> lockToCam("ui.Lock to cam", false, true); pangolin::Var<int> show_slice("ui.show slice",MAXD/2, 0, MAXD-1); pangolin::Var<int> maxdisp("ui.maxdisp",MAXD, 0, MAXD); pangolin::Var<bool> subpix("ui.subpix", true, true); pangolin::Var<bool> use_census("ui.use census", true, true); pangolin::Var<int> avg_rad("ui.avg_rad",0, 0, 100); pangolin::Var<bool> do_dtam("ui.do dtam", false, true); pangolin::Var<bool> dtam_reset("ui.reset", false, false); pangolin::Var<float> g_alpha("ui.g alpha", 14, 0,4); pangolin::Var<float> g_beta("ui.g beta", 2.5, 0,2); pangolin::Var<float> theta("ui.theta", 100, 0,100); pangolin::Var<float> lambda("ui.lambda", 20, 0,20); pangolin::Var<float> sigma_q("ui.sigma q", 0.7, 0, 1); pangolin::Var<float> sigma_d("ui.sigma d", 0.7, 0, 1); pangolin::Var<float> huber_alpha("ui.huber alpha", 0.002, 0, 0.01); pangolin::Var<float> beta("ui.beta", 0.00001, 0, 0.01); pangolin::Var<float> alpha("ui.alpha", 0.9, 0,1); pangolin::Var<float> r1("ui.r1", 100, 0,0.01); pangolin::Var<float> r2("ui.r2", 100, 0,0.01); pangolin::Var<bool> filter("ui.filter", false, true); pangolin::Var<float> eps("ui.eps",0.01*0.01, 0, 0.01); pangolin::Var<int> rad("ui.radius",9, 1, 20); pangolin::Var<bool> leftrightcheck("ui.left-right check", false, true); pangolin::Var<float> maxdispdiff("ui.maxdispdiff",1, 0, 5); pangolin::Var<int> domedits("ui.median its",1, 1, 10); pangolin::Var<bool> domed9x9("ui.median 9x9", false, true); pangolin::Var<bool> domed7x7("ui.median 7x7", false, true); pangolin::Var<bool> domed5x5("ui.median 5x5", false, true); pangolin::Var<int> medi("ui.medi",12, 0, 24); pangolin::Var<float> filtgradthresh("ui.filt grad thresh", 0, 0, 20); pangolin::Var<bool> save_depthmaps("ui.save_depthmaps", false, true); int jump_frames = 0; pangolin::RegisterKeyPressCallback(' ', [&run](){run = !run;} ); pangolin::RegisterKeyPressCallback('l', [&lockToCam](){lockToCam = !lockToCam;} ); pangolin::RegisterKeyPressCallback(pangolin::PANGO_SPECIAL + GLUT_KEY_RIGHT, [&step](){step=true;} ); pangolin::RegisterKeyPressCallback(']', [&jump_frames](){jump_frames=100;} ); pangolin::RegisterKeyPressCallback('}', [&jump_frames](){jump_frames=1000;} ); pangolin::Handler2dImageSelect handler2d(lw,lh,level); // ActivateDrawPyramid<unsigned char,max_levels> adleft(img_pyr[0],GL_LUMINANCE8, false, true); // ActivateDrawPyramid<unsigned char,max_levels> adright(img_pyr[1],GL_LUMINANCE8, false, true); pangolin::ActivateDrawImage<float> adleft(img[0],GL_LUMINANCE32F_ARB, false, true); pangolin::ActivateDrawImage<float> adright(img[1],GL_LUMINANCE32F_ARB, false, true); pangolin::ActivateDrawImage<float> adisp(disp[0],GL_LUMINANCE32F_ARB, false, true); pangolin::ActivateDrawImage<float> adw(imgw,GL_LUMINANCE32F_ARB, false, true); // ActivateDrawImage<float> adCrossSection(dCrossSection,GL_RGBA_FLOAT32_APPLE, false, true); pangolin::ActivateDrawImage<float> adVol(vol[0].ImageXY(show_slice),GL_LUMINANCE32F_ARB, false, true); SceneGraph::GLSceneGraph graph; SceneGraph::GLVbo glvbo(&vbo,&ibo,&cbo); graph.AddChild(&glvbo); SetupContainer(container, 6, (float)w/h); container[0].SetDrawFunction(boost::ref(adleft)).SetHandler(&handler2d); container[1].SetDrawFunction(boost::ref(adright)).SetHandler(&handler2d); container[2].SetDrawFunction(boost::ref(adisp)).SetHandler(&handler2d); container[3].SetDrawFunction(boost::ref(adVol)).SetHandler(&handler2d); container[4].SetDrawFunction(SceneGraph::ActivateDrawFunctor(graph, s_cam)) .SetHandler( new pangolin::Handler3D(s_cam, pangolin::AxisNone) ); container[5].SetDrawFunction(boost::ref(adw)).SetHandler(&handler2d); for(unsigned long frame=0; !pangolin::ShouldQuit();) { bool go = frame==0 || jump_frames > 0 || run || Pushed(step); for(; jump_frames > 0; jump_frames--) { video.Capture(images); } if(go) { if(frame>0) { if( video.Capture(images) == false) { exit(1); } } frame++; ///////////////////////////////////////////////////////////// // Upload images to device (Warp / Decimate if necessery) for(int i=0; i<2; ++i ) { hCamImg[i].ptr = images[i].data(); if(rectify) { upload.CopyFrom(hCamImg[i].SubImage(roi)); Warp(img_pyr[i][0], upload, dLookup[i]); }else{ img_pyr[i][0].CopyFrom(hCamImg[i].SubImage(roi)); } roo::BoxReduce<unsigned char, max_levels, unsigned int>(img_pyr[i]); } } go |= avg_rad.GuiChanged() | use_census.GuiChanged(); if( go ) { for(int i=0; i<2; ++i ) { roo::ElementwiseScaleBias<float,unsigned char,float>(img[i], img_pyr[i][level],1.0f/255.0f); if(avg_rad > 0 ) { roo::BoxFilter<float,float,float>(temp[0],img[i],Scratch,avg_rad); roo::ElementwiseAdd<float,float,float,float>(img[i], img[i], temp[0], 1, -1, 0.5); } if(use_census) { Census(census[i], img[i]); } } } if( go | g_alpha.GuiChanged() || g_beta.GuiChanged() ) { ExponentialEdgeWeight(imgw, img[0], g_alpha, g_beta); } go |= filter.GuiChanged() | leftrightcheck.GuiChanged() | rad.GuiChanged() | eps.GuiChanged() | alpha.GuiChanged() | r1.GuiChanged() | r2.GuiChanged(); if(go) { if(use_census) { roo::CensusStereoVolume<float, census_t>(vol[0], census[0], census[1], maxdisp, -1); if(leftrightcheck) roo::CensusStereoVolume<float, census_t>(vol[1], census[1], census[0], maxdisp, +1); }else{ CostVolumeFromStereoTruncatedAbsAndGrad(vol[0], img[0], img[1], -1, alpha, r1, r2); if(leftrightcheck) CostVolumeFromStereoTruncatedAbsAndGrad(vol[1], img[1], img[0], +1, alpha, r1, r2); } if(filter) { // Filter Cost volume for(int v=0; v<(leftrightcheck?2:1); ++v) { roo::Image<float, roo::TargetDevice, roo::Manage>& I = img[v]; roo::ComputeMeanVarience<float,float,float>(varI, temp[0], meanI, I, Scratch, rad); for(int d=0; d<maxdisp; ++d) { roo::Image<float> P = vol[v].ImageXY(d); roo::ComputeCovariance(temp[0],temp[2],temp[1],P,meanI,I,Scratch,rad); GuidedFilter(P,temp[0],varI,temp[1],meanI,I,Scratch,temp[2],temp[3],temp[4],rad,eps); } } } } static int n = 0; // static float theta = 0; // go |= Pushed(dtam_reset); // if(go ) if(Pushed(dtam_reset)) { n = 0; theta.Reset(); // Initialise primal and auxillary variables CostVolMinimumSubpix(imgd,vol[0], maxdisp,-1); imga.CopyFrom(imgd); // Initialise dual variable imgq.Memset(0); } const double min_theta = 1E-0; if(do_dtam && theta > min_theta) { for(int i=0; i<5; ++i ) { // Auxillary exhaustive search CostVolMinimumSquarePenaltySubpix(imga, vol[0], imgd, maxdisp, -1, lambda, (theta) ); // Dual Ascent roo::WeightedHuberGradU_DualAscentP(imgq, imgd, imgw, sigma_q, huber_alpha); // Primal Descent roo::WeightedL2_u_minus_g_PrimalDescent(imgd, imgq, imga, imgw, sigma_d, 1.0f / (theta) ); theta= theta * (1-beta*n); ++n; } if( theta <= min_theta && save_depthmaps ) { cv::Mat dmap = cv::Mat( lh, lw, CV_32FC1 ); // convert disparity to depth roo::Disp2Depth(imgd, depthmap, Kl(0,0), baseline ); depthmap.MemcpyToHost( dmap.data ); // save depth image char Index[10]; sprintf( Index, "%05d", frame ); std::string DepthPrefix = "SDepth-"; std::string DepthFile; DepthFile = DepthPrefix + Index + ".pdm"; std::cout << "Depth File: " << DepthFile << std::endl; std::ofstream pDFile( DepthFile.c_str(), std::ios::out | std::ios::binary ); pDFile << "P7" << std::endl; pDFile << dmap.cols << " " << dmap.rows << std::endl; unsigned int Size = dmap.elemSize1() * dmap.rows * dmap.cols; pDFile << 4294967295 << std::endl; pDFile.write( (const char*)dmap.data, Size ); pDFile.close(); // save grey image std::string GreyPrefix = "Left-"; std::string GreyFile; GreyFile = GreyPrefix + Index + ".pgm"; std::cout << "Grey File: " << GreyFile << std::endl; cv::Mat gimg = cv::Mat( lh, lw, CV_8UC1 ); img_pyr[0][level].MemcpyToHost( gimg.data ); cv::imwrite( GreyFile, gimg ); // reset step = true; dtam_reset = true; } } go |= pangolin::GuiVarHasChanged(); // if(go) { // if(subpix) { // CostVolMinimumSubpix(disp[0],vol[0], maxdisp,-1); // if(leftrightcheck) CostVolMinimumSubpix(disp[1],vol[1], maxdisp,+1); // }else{ // CostVolMinimum<float,float>(disp[0],vol[0], maxdisp); // if(leftrightcheck) CostVolMinimum<float,float>(disp[1],vol[1], maxdisp); // } // } if(go) { for(int di=0; di<(leftrightcheck?2:1); ++di) { for(int i=0; i < domedits; ++i ) { if(domed9x9) MedianFilterRejectNegative9x9(disp[di],disp[di], medi); if(domed7x7) MedianFilterRejectNegative7x7(disp[di],disp[di], medi); if(domed5x5) MedianFilterRejectNegative5x5(disp[di],disp[di], medi); } } if(leftrightcheck ) { LeftRightCheck(disp[1], disp[0], +1, maxdispdiff); LeftRightCheck(disp[0], disp[1], -1, maxdispdiff); } if(filtgradthresh > 0) { FilterDispGrad(disp[0], disp[0], filtgradthresh); } } // if(go) { // Generate point cloud from disparity image DisparityImageToVbo(d3d, disp[0], baseline, Kl(0,0), Kl(1,1), Kl(0,2), Kl(1,2) ); // if(container[3].IsShown()) { // Copy point cloud into VBO { pangolin::CudaScopedMappedPtr var(vbo); roo::Image<float4> dVbo((float4*)*var,lw,lh); dVbo.CopyFrom(d3d); } // Generate CBO { pangolin::CudaScopedMappedPtr var(cbo); roo::Image<uchar4> dCbo((uchar4*)*var,lw,lh); roo::ConvertImage<uchar4,unsigned char>(dCbo, img_pyr[0][level]); } } // Update texture views adisp.SetImageScale(1.0f/maxdisp); // adleft.SetLevel(show_level); // adright.SetLevel(show_level); adVol.SetImage(vol[0].ImageXY(show_slice)); } ///////////////////////////////////////////////////////////// // Draw glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1,1,1); pangolin::FinishFrame(); } }
void liveAdvectTexture(){ Window::init(); Window window("Realtime Texture Advection"); //Set an fps cap const float FPS = 60.0f; //Setup a quad to draw too GL::VertexArray vao; vao.elementBuffer(quadElems); GL::VertexBuffer vbo(quad, GL::USAGE::STATIC_DRAW); //Setup program GL::Program prog("../res/shader.v.glsl", "../res/shader.f.glsl"); //Setup the attributes vao.setAttribPointer(vbo, prog.getAttribute("position"), 3, GL_FLOAT, GL_FALSE); vao.setAttribPointer(vbo, prog.getAttribute("texIn"), 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * 4)); glm::mat4 view = glm::lookAt<float>(glm::vec3(0, 0, 1), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0)); glm::mat4 proj = glm::perspective(60.0f, (float)(window.box().w) / (float)(window.box().h), 0.1f, 100.0f); glm::mat4 model = glm::scale(0.55f, 0.55f, 1.0f); glm::mat4 mvp = proj * view * model; prog.uniformMat4x4("mvp", mvp); /* * I don't think OpenCL or OpenGL provide a simple method for copying images/textures so * instead we'll flip the in/out image each step and draw the out image by setting active = out */ //Make textures to work with GL::Texture texA("../res/map.png", true, SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB); GL::Texture texB("../res/blank.png", true, SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB); //Active is the actual texture we will draw GL::Texture active = texB; //Setup our OpenCL context + program and kernel CL::TinyCL tiny(CL::DEVICE::GPU, true); cl::Program program = tiny.loadProgram("../res/simpleAdvect.cl"); cl::Kernel kernel = tiny.loadKernel(program, "simpleAdvect"); //Setup our OpenCL data #ifdef CL_VERSION_1_2 cl::ImageGL imgA = tiny.imageFromTexture(CL::MEM::READ_WRITE, texA); cl::ImageGL imgB = tiny.imageFromTexture(CL::MEM::READ_WRITE, texB); #else cl::Image2DGL imgA = tiny.imageFromTexture(CL::MEM::READ_WRITE, texA); cl::Image2DGL imgB = tiny.imageFromTexture(CL::MEM::READ_WRITE, texB); #endif const float speed = 0.2f; float velocity[2] = { 0.0f, 0.0f }; cl::Buffer velBuf = tiny.buffer(CL::MEM::READ_ONLY, 2 * sizeof(float), velocity); //Setup our GL objects vector std::vector<cl::Memory> glObjs; glObjs.push_back(imgA); glObjs.push_back(imgB); //The time step will be constant and velocity won't change each step, so set'em now float dt = 1.0f / FPS; kernel.setArg(0, sizeof(float), &dt); kernel.setArg(1, velBuf); //Query the preferred work group size int workSize = tiny.preferredWorkSize(kernel); //fixed for now int imgSize = 256; cl::NDRange local(workSize, workSize); cl::NDRange global(imgSize, imgSize); //Track the run number so we know which texture to set as in/out and which to draw int run = 0; //Our event structure SDL_Event e; //Limit framerate with a timer Timer delta; //For tracking if we want to quit bool quit = false, paused = false; while (!quit){ delta.Start(); //Event Polling while (SDL_PollEvent(&e)){ //If user closes he window if (e.type == SDL_QUIT) quit = true; //If user presses any key if (e.type == SDL_KEYDOWN){ switch (e.key.keysym.sym){ //So we can change velocity case SDLK_w: velocity[1] = speed; tiny.writeData(velBuf, 2 * sizeof(float), velocity); break; case SDLK_s: velocity[1] = -speed; tiny.writeData(velBuf, 2 * sizeof(float), velocity); break; case SDLK_a: velocity[0] = -speed; tiny.writeData(velBuf, 2 * sizeof(float), velocity); break; case SDLK_d: velocity[0] = speed; tiny.writeData(velBuf, 2 * sizeof(float), velocity); break; case SDLK_r: velocity[0] = 0.0f; velocity[1] = 0.0f; tiny.writeData(velBuf, 2 * sizeof(float), velocity); break; //Toggle pause case SDLK_SPACE: paused = !paused; break; //For quitting, escape key case SDLK_ESCAPE: quit = true; break; default: break; } } } //Run the kernel, setting the in/out textures properly. On even runs the output will be //in texB, on odd runs output will be in texA if (!paused){ try { //On even runs and the first run texB/imgB is our output, on odd runs it's flipped //Is this really the best way to do this? Maybe there is some faster way to copy the image over //instead of updating this each time if (run % 2 == 0 || run == 0){ kernel.setArg(2, imgA); kernel.setArg(3, imgB); active = texB; } else { kernel.setArg(2, imgB); kernel.setArg(3, imgA); active = texA; } glFinish(); tiny.mQueue.enqueueAcquireGLObjects(&glObjs); tiny.runKernel(kernel, local, global); tiny.mQueue.enqueueReleaseGLObjects(&glObjs); tiny.mQueue.finish(); ++run; } catch (const cl::Error &e){ std::cout << "Error: " << e.what() << " code: " << e.err() << std::endl; } } //RENDERING window.clear(); prog.use(); glBindVertexArray(vao); glActiveTexture(GL_TEXTURE0); //Shouldn't we be drawing active here? glBindTexture(GL_TEXTURE_2D, texA); glDrawElements(GL_TRIANGLES, vao.numElements(), GL_UNSIGNED_SHORT, NULL); window.present(); //Cap fps if (delta.Ticks() < 1000 / FPS) SDL_Delay(1000 / FPS - delta.Ticks()); } window.close(); Window::quit(); }
unique_ptr<RenderableObject> RenderableObject::box(const glm::vec3 &mi, const glm::vec3 &ma, const glm::vec4 &color, GLenum primitive) { vector<glm::vec3> vertices; vector<glm::vec3> normals; // Face 1 vertices.push_back(glm::vec3(mi.x, ma.y, mi.z)); vertices.push_back(glm::vec3(mi.x, ma.y, ma.z)); vertices.push_back(glm::vec3(ma.x, ma.y, ma.z)); vertices.push_back(glm::vec3(ma.x, ma.y, mi.z)); normals.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); // Face 2 vertices.push_back(glm::vec3(mi.x, mi.y, mi.z)); vertices.push_back(glm::vec3(ma.x, mi.y, mi.z)); vertices.push_back(glm::vec3(ma.x, mi.y, ma.z)); vertices.push_back(glm::vec3(mi.x, mi.y, ma.z)); normals.push_back(glm::vec3(0.0f, -1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, -1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, -1.0f, 0.0f)); normals.push_back(glm::vec3(0.0f, -1.0f, 0.0f)); // Face 3 vertices.push_back(glm::vec3(mi.x, mi.y, mi.z)); vertices.push_back(glm::vec3(mi.x, ma.y, mi.z)); vertices.push_back(glm::vec3(ma.x, ma.y, mi.z)); vertices.push_back(glm::vec3(ma.x, mi.y, mi.z)); normals.push_back(glm::vec3(0.0f, 0.0f, -1.0f)); normals.push_back(glm::vec3(0.0f, 0.0f, -1.0f)); normals.push_back(glm::vec3(0.0f, 0.0f, -1.0f)); normals.push_back(glm::vec3(0.0f, 0.0f, -1.0f)); // Face 4 vertices.push_back(glm::vec3(mi.x, mi.y, ma.z)); vertices.push_back(glm::vec3(ma.x, mi.y, ma.z)); vertices.push_back(glm::vec3(ma.x, ma.y, ma.z)); vertices.push_back(glm::vec3(mi.x, ma.y, ma.z)); normals.push_back(glm::vec3(0.0f, 0.0f, 1.0f)); normals.push_back(glm::vec3(0.0f, 0.0f, 1.0f)); normals.push_back(glm::vec3(0.0f, 0.0f, 1.0f)); normals.push_back(glm::vec3(0.0f, 0.0f, 1.0f)); // Face 5 vertices.push_back(glm::vec3(mi.x, mi.y, mi.z)); vertices.push_back(glm::vec3(mi.x, mi.y, ma.z)); vertices.push_back(glm::vec3(mi.x, ma.y, ma.z)); vertices.push_back(glm::vec3(mi.x, ma.y, mi.z)); normals.push_back(glm::vec3(-1.0f, 0.0f, 0.0f)); normals.push_back(glm::vec3(-1.0f, 0.0f, 0.0f)); normals.push_back(glm::vec3(-1.0f, 0.0f, 0.0f)); normals.push_back(glm::vec3(-1.0f, 0.0f, 0.0f)); // Face 6 vertices.push_back(glm::vec3(ma.x, mi.y, mi.z)); vertices.push_back(glm::vec3(ma.x, ma.y, mi.z)); vertices.push_back(glm::vec3(ma.x, ma.y, ma.z)); vertices.push_back(glm::vec3(ma.x, mi.y, ma.z)); normals.push_back(glm::vec3(1.0f, 0.0f, 0.0f)); normals.push_back(glm::vec3(1.0f, 0.0f, 0.0f)); normals.push_back(glm::vec3(1.0f, 0.0f, 0.0f)); normals.push_back(glm::vec3(1.0f, 0.0f, 0.0f)); // Indices vector<GLuint> indices ={ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15 }; uint nrVertices = vertices.size(); vector<RenderableObject::Vertex> attrData(nrVertices); for(uint i=0; i<nrVertices; ++i) { glm::vec3 v = vertices[i]; glm::vec3 n = normals[i]; attrData[i].Position = v; attrData[i].Normal = n; attrData[i].Color = color; } unique_ptr<RenderableObject> vbo(new RenderableObject); vbo->setData(attrData, indices, primitive); return vbo; }
int main() { if(-1 == SDL_Init(SDL_INIT_VIDEO)) { std::cerr << "Unable to initialize SDL" << std::endl; return EXIT_FAILURE; } if(NULL == SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP, SDL_OPENGL)) { std::cerr << "Unable to open the window and get an OpenGL context" << std::endl; return EXIT_FAILURE; } SDL_WM_SetCaption("OpenGL4Imacs", NULL); GLenum glewCode = glewInit(); if(GLEW_OK != glewCode) { std::cerr << "Unable to initialize GLEW : " << glewGetErrorString(glewCode) << std::endl; return EXIT_FAILURE; } Button2D jouer(-1,-1,0.5,0.2); // Initialisation VBO glimac::LowLevelVBO vbo(jouer.getVertices(), 8 * sizeof(GLfloat), GL_STATIC_DRAW, GL_ARRAY_BUFFER); // Initialisation VAO glimac::VAO vao; // Binder le vao vao.bind(); glEnableVertexAttribArray(0); // Binder le vbo vbo.bind(); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (const GLvoid*) (0 * sizeof(GLfloat))); glBindBuffer(GL_ARRAY_BUFFER, 0); // Debinder le vao glBindVertexArray(0); bool done = false; while(!done) { Uint32 tStart = SDL_GetTicks(); // Rendering code goes here glClear(GL_COLOR_BUFFER_BIT); vao.bind(); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glBindVertexArray(0); // Application code goes here SDL_Event e; while(SDL_PollEvent(&e)) { switch(e.type) { default: break; case SDL_QUIT: done = true; break; } } // Mise à jour de la fenêtre (synchronisation implicite avec OpenGL) SDL_GL_SwapBuffers(); Uint32 tEnd = SDL_GetTicks(); Uint32 d = tEnd - tStart; if(d < FRAME_DURATION) { SDL_Delay(FRAME_DURATION - d); } } // Destruction des ressources SDL_Quit(); return EXIT_SUCCESS; }
void SceneManagerTriangle::InitScene(uint16 width, uint16 height) { m_width = width; m_height = height; float cube[] = { -1, -1, 0, 1, -1, 1, 0, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1.5, -1.5, -1, 1, -1.5, 1.5, -1, 1, 1.5, 1.5, -1, 1, 1.5, -1.5, -1, 1, }; //uint32 cubeColor[] = { // 0xff0000, // 0x00ff00, // 0x0000ff, // 0xff0000, //}; float uv[] = { 0.0f, 1.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, }; float cubeNormal[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, }; uint32 cubeIndex[] = { 0, 2, 1, 0, 3, 2, //4, 6, 5, //4, 7, 6, }; shared_ptr<VertexBufferObject> vbo(new VertexBufferObject()); vbo->CopyVertexBuffer(cube, sizeof(cube) / sizeof(float)); //vbo->CopyColorBuffer(cubeColor, sizeof(cubeColor) / sizeof(uint32)); vbo->CopyUVBuffer(uv, sizeof(uv) / sizeof(float)); //vbo->CopyNormalBuffer(cubeNormal, sizeof(cubeNormal) / sizeof(float)); vbo->CopyIndexBuffer(cubeIndex, sizeof(cubeIndex) / sizeof(uint32)); vbo->m_mode = VertexBufferObject::RENDER_TRIANGLE; //vbo->m_mode = VertexBufferObject::RENDER_LINE; vbo->m_cullMode = VertexBufferObject::CULL_NONE; Soft3dPipeline::Instance()->SetVBO(vbo); uint32 tex_data[] = { 0xa7dbff, 0xefed7a, 0xb8ecff, 0x136888, 0xeb5f25, 0x136999, 0xefed7a, 0xb8ecff, 0xefed7a, 0xeb5f25, 0x136999, 0xeb5f25, 0xb8ecff, 0xefed7a, 0xb8ecff, 0x136999, 0xeb5f25, 0x136999, }; shared_ptr<Texture> tex(new Texture()); tex->CopyFromBuffer(tex_data, 6, 3); tex->filter_mode = Texture::NEAREST; Soft3dPipeline::Instance()->SetTexture(tex); Soft3dPipeline::Instance()->AddKeyboardEventCB(boost::bind(&SceneManagerTriangle::KeyboardEventCB, this, _1)); }
osg::ref_ptr<osg::Node> MeshManager::loadFlat(size_t texid, bool centered, size_t *num_frames) { auto iter = mFlatCache.find(std::make_pair(texid, centered)); if(iter != mFlatCache.end()) { osg::ref_ptr<osg::Node> node; if(iter->second.lock(node)) { if(num_frames) { osg::ref_ptr<osg::Texture> tex = TextureManager::get().getTexture(texid); *num_frames = tex->getTextureDepth(); } return node; } } if(!mFlatProgram) { mFlatProgram = new osg::Program(); mFlatProgram->addShader(osgDB::readShaderFile(osg::Shader::VERTEX, "shaders/sprite.vert")); mFlatProgram->addShader(osgDB::readShaderFile(osg::Shader::FRAGMENT, "shaders/sprite.frag")); } int16_t xoffset, yoffset; float xscale, yscale; osg::ref_ptr<osg::Texture> tex = TextureManager::get().getTexture( texid, &xoffset, &yoffset, &xscale, &yscale ); if(num_frames) *num_frames = tex->getTextureDepth(); float width = tex->getTextureWidth(); float height = tex->getTextureHeight(); osg::Matrix mat(osg::Matrixf::scale(xscale, yscale, xscale)); //mat.postMultTranslate(osg::Vec3(xoffset, yoffset, 0)); seems to be incorrect values?? osg::ref_ptr<osg::MatrixTransform> base(new osg::MatrixTransform(mat)); osg::ref_ptr<osg::Billboard> bb(new osg::Billboard()); bb->setMode(osg::Billboard::AXIAL_ROT); bb->setAxis(osg::Vec3(0.0f, 1.0f, 0.0f)); bb->setNormal(osg::Vec3(0.0f, 0.0f, -1.0f)); osg::ref_ptr<osg::Vec3Array> vtxs(new osg::Vec3Array(4)); (*vtxs)[0] = osg::Vec3(width* 0.5f, height*-0.5f, 0.0f); (*vtxs)[1] = osg::Vec3(width*-0.5f, height*-0.5f, 0.0f); (*vtxs)[2] = osg::Vec3(width*-0.5f, height* 0.5f, 0.0f); (*vtxs)[3] = osg::Vec3(width* 0.5f, height* 0.5f, 0.0f); osg::ref_ptr<osg::Vec2Array> texcrds(new osg::Vec2Array(4)); (*texcrds)[0] = osg::Vec2(1.0f, 0.0f); (*texcrds)[1] = osg::Vec2(0.0f, 0.0f); (*texcrds)[2] = osg::Vec2(0.0f, 1.0f); (*texcrds)[3] = osg::Vec2(1.0f, 1.0f); osg::ref_ptr<osg::Vec3Array> nrms(new osg::Vec3Array(4)); (*nrms)[0] = osg::Vec3(0.0f, 0.0f, -1.0f); (*nrms)[1] = osg::Vec3(0.0f, 0.0f, -1.0f); (*nrms)[2] = osg::Vec3(0.0f, 0.0f, -1.0f); (*nrms)[3] = osg::Vec3(0.0f, 0.0f, -1.0f); osg::ref_ptr<osg::Vec4ubArray> colors(new osg::Vec4ubArray(4)); (*colors)[0] = osg::Vec4ub(255, 255, 255, 255); (*colors)[1] = osg::Vec4ub(255, 255, 255, 255); (*colors)[2] = osg::Vec4ub(255, 255, 255, 255); (*colors)[3] = osg::Vec4ub(255, 255, 255, 255); colors->setNormalize(true); osg::ref_ptr<osg::VertexBufferObject> vbo(new osg::VertexBufferObject()); vtxs->setVertexBufferObject(vbo); texcrds->setVertexBufferObject(vbo); nrms->setVertexBufferObject(vbo); colors->setVertexBufferObject(vbo); osg::ref_ptr<osg::Geometry> geometry(new osg::Geometry); geometry->setVertexArray(vtxs); geometry->setTexCoordArray(0, texcrds, osg::Array::BIND_PER_VERTEX); geometry->setNormalArray(nrms, osg::Array::BIND_PER_VERTEX); geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); geometry->setUseDisplayList(false); geometry->setUseVertexBufferObjects(true); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4)); osg::StateSet *ss = geometry->getOrCreateStateSet(); ss->setAttributeAndModes(mFlatProgram); // Alpha test is reversed, because the shader will set alpha=0 for texels // that should be kept, and consequently have no specular, and alpha=1 for // texels that should be dropped. ss->setAttributeAndModes(new osg::AlphaFunc(osg::AlphaFunc::LESS, 0.5f)); ss->addUniform(new osg::Uniform("diffuseTex", 0)); ss->setTextureAttribute(0, tex); if(centered) bb->addDrawable(geometry); else bb->addDrawable(geometry, osg::Vec3(0.0f, height*-0.5f, 0.0f)); base->addChild(bb); mFlatCache[std::make_pair(texid, centered)] = osg::ref_ptr<osg::Node>(base); return base; }
osg::ref_ptr<osg::Node> MeshManager::get(size_t idx) { /* Not sure if this cache is a good idea since it shares the whole model * tree. OSG can parent the same sub-tree to multiple points, which should * be okay as long as the individual sub-trees don't need changing. */ auto iter = mModelCache.find(idx); if(iter != mModelCache.end()) { osg::ref_ptr<osg::Node> node; if(iter->second.lock(node)) return node; } if(!mModelProgram) { mModelProgram = new osg::Program(); mModelProgram->addShader(osgDB::readShaderFile(osg::Shader::VERTEX, "shaders/object.vert")); mModelProgram->addShader(osgDB::readShaderFile(osg::Shader::FRAGMENT, "shaders/object.frag")); } DFOSG::Mesh *mesh = DFOSG::MeshLoader::get().load(idx); osg::ref_ptr<osg::Geode> geode(new osg::Geode()); for(auto iter = mesh->getPlanes().begin();iter != mesh->getPlanes().end();) { osg::ref_ptr<osg::Vec3Array> vtxs(new osg::Vec3Array()); osg::ref_ptr<osg::Vec3Array> nrms(new osg::Vec3Array()); osg::ref_ptr<osg::Vec3Array> binrms(new osg::Vec3Array()); osg::ref_ptr<osg::Vec2Array> texcrds(new osg::Vec2Array()); osg::ref_ptr<osg::Vec4ubArray> colors(new osg::Vec4ubArray()); osg::ref_ptr<osg::DrawElementsUShort> idxs(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES)); uint16_t texid = iter->getTextureId(); osg::ref_ptr<osg::Texture> tex = TextureManager::get().getTexture(texid); float width = tex->getTextureWidth(); float height = tex->getTextureHeight(); do { const std::vector<DFOSG::MdlPlanePoint> &pts = iter->getPoints(); size_t last_total = vtxs->size(); vtxs->resize(last_total + pts.size()); nrms->resize(last_total + pts.size()); binrms->resize(last_total + pts.size()); texcrds->resize(last_total + pts.size()); colors->resize(last_total + pts.size()); idxs->resize((last_total + pts.size() - 2) * 3); size_t j = last_total; for(const DFOSG::MdlPlanePoint &pt : pts) { uint32_t vidx = pt.getIndex(); (*vtxs)[j].x() = mesh->getPoints()[vidx].x() / 256.0f; (*vtxs)[j].y() = mesh->getPoints()[vidx].y() / 256.0f; (*vtxs)[j].z() = mesh->getPoints()[vidx].z() / 256.0f; (*nrms)[j].x() = iter->getNormal().x() / 256.0f; (*nrms)[j].y() = iter->getNormal().y() / 256.0f; (*nrms)[j].z() = iter->getNormal().z() / 256.0f; (*binrms)[j].x() = iter->getBinormal().x() / 256.0f; (*binrms)[j].y() = iter->getBinormal().y() / 256.0f; (*binrms)[j].z() = iter->getBinormal().z() / 256.0f; (*texcrds)[j].x() = pt.u() / width; (*texcrds)[j].y() = pt.v() / height; (*colors)[j] = osg::Vec4ub(255, 255, 255, 255); if(j >= last_total+2) { (*idxs)[(j-2)*3 + 0] = last_total; (*idxs)[(j-2)*3 + 1] = j-1; (*idxs)[(j-2)*3 + 2] = j; } ++j; } } while(++iter != mesh->getPlanes().end() && iter->getTextureId() == texid); osg::ref_ptr<osg::VertexBufferObject> vbo(new osg::VertexBufferObject()); vtxs->setVertexBufferObject(vbo); nrms->setVertexBufferObject(vbo); texcrds->setVertexBufferObject(vbo); colors->setVertexBufferObject(vbo); colors->setNormalize(true); osg::ref_ptr<osg::ElementBufferObject> ebo(new osg::ElementBufferObject()); idxs->setElementBufferObject(ebo); osg::ref_ptr<osg::Geometry> geometry(new osg::Geometry); geometry->setVertexArray(vtxs); geometry->setNormalArray(nrms, osg::Array::BIND_PER_VERTEX); geometry->setTexCoordArray(1, binrms, osg::Array::BIND_PER_VERTEX); geometry->setTexCoordArray(0, texcrds, osg::Array::BIND_PER_VERTEX); geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); geometry->setUseDisplayList(false); geometry->setUseVertexBufferObjects(true); geometry->addPrimitiveSet(idxs); /* Cache the stateset used for this texture, so it can be reused for * multiple models (should help OSG batch together objects with similar * state). */ auto &stateiter = mStateSetCache[texid]; osg::ref_ptr<osg::StateSet> ss; if(stateiter.lock(ss) && ss) geometry->setStateSet(ss); else { ss = geometry->getOrCreateStateSet(); ss->setAttributeAndModes(mModelProgram); ss->addUniform(new osg::Uniform("diffuseTex", 0)); ss->setTextureAttribute(0, tex); stateiter = ss; } geode->addDrawable(geometry); } mModelCache[idx] = osg::ref_ptr<osg::Node>(geode); return geode; }
void SimpleFluid::testVelocityField(){ //Setup a quad to draw too GL::VertexArray vao; vao.elementBuffer(quadElems); GL::VertexBuffer vbo(quad, GL::USAGE::STATIC_DRAW); //Setup program GL::Program prog("../res/shader.v.glsl", "../res/shader.f.glsl"); //Setup the attributes vao.setAttribPointer(vbo, prog.getAttribute("position"), 3, GL_FLOAT, GL_FALSE); vao.setAttribPointer(vbo, prog.getAttribute("texIn"), 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * 4)); glm::mat4 view = glm::lookAt<float>(glm::vec3(0, 0, 1), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0)); //I suppose later I should pass in the window w/h for setting this properly glm::mat4 proj = glm::perspective(60.0f, static_cast<float>(window.box().w) / static_cast<float>(window.box().h), 0.1f, 100.0f); glm::mat4 model = glm::scale(0.35f, 0.35f, 1.0f); glm::mat4 mvp = proj * view * model; prog.uniformMat4x4("mvp", mvp); //Make textures to work with GL::Texture fieldA("../res/simplefluid/fluid32.png", true, SOIL_FLAG_INVERT_Y); GL::Texture fieldB("../res/simplefluid/fluid32.png", true, SOIL_FLAG_INVERT_Y); GL::Texture velocity("../res/simplefluid/right_velocity_32.png", true, SOIL_FLAG_INVERT_Y); //Output is the advection output texture, which will flip each run GL::Texture output = fieldB; //Setup our OpenCL data #ifdef CL_VERSION_1_2 cl::ImageGL imgA = tiny.imageFromTexture(CL::MEM::READ_WRITE, fieldA); cl::ImageGL imgB = tiny.imageFromTexture(CL::MEM::READ_WRITE, fieldB); cl::ImageGL imgVel = tiny.imageFromTexture(CL::MEM::READ_ONLY, velocity); #else cl::Image2DGL imgA = tiny.imageFromTexture(CL::MEM::READ_WRITE, fieldA); cl::Image2DGL imgB = tiny.imageFromTexture(CL::MEM::READ_WRITE, fieldB); cl::Image2DGL imgVel = tiny.imageFromTexture(CL::MEM::READ_ONLY, velocity); #endif std::vector<cl::Memory> glObjs; glObjs.push_back(imgA); glObjs.push_back(imgB); glObjs.push_back(imgVel); cl::Program advectProgram = tiny.loadProgram("../res/simplefluid/advectImageField.cl"); cl::Kernel advect = tiny.loadKernel(advectProgram, "advectImageField"); //We'll pick an arbitray time step for now advect.setArg(0, 1.f / 30.f); advect.setArg(1, imgVel); advect.setArg(2, imgA); advect.setArg(3, imgB); int workSize = tiny.preferredWorkSize(advect); cl::NDRange local(workSize, workSize); cl::NDRange global(dim, dim); //We use the run number to decide which field image should be input and which should be output //on even runs A is in, B is out and odd runs we flip int run = 0; Input::Init(); while (!Input::Quit()){ Input::PollEvents(); if (Input::KeyDown(SDL_SCANCODE_ESCAPE)) Input::Quit(true); //Advect the field if (run % 2 == 0 || run == 0){ advect.setArg(2, imgA); advect.setArg(3, imgB); output = fieldB; } else { advect.setArg(2, imgB); advect.setArg(3, imgA); output = fieldA; } glFinish(); tiny.mQueue.enqueueAcquireGLObjects(&glObjs); tiny.runKernel(advect, local, global); tiny.mQueue.enqueueReleaseGLObjects(&glObjs); tiny.mQueue.finish(); ++run; //RENDERING window.clear(); prog.use(); glBindVertexArray(vao); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, output); glDrawElements(GL_TRIANGLES, vao.numElements(), GL_UNSIGNED_SHORT, NULL); window.present(); } }
osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter) { if (chunkSize * mNumSplits > 1.f) { // keep splitting osg::ref_ptr<osg::Group> group (new osg::Group); if (parent) parent->addChild(group); float newChunkSize = chunkSize/2.f; buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, newChunkSize/2.f)); buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize/2.f, -newChunkSize/2.f)); buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize/2.f, newChunkSize/2.f)); buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize/2.f, -newChunkSize/2.f)); return group; } else { float minH, maxH; if (!mStorage->getMinMaxHeights(chunkSize, chunkCenter, minH, maxH)) return NULL; // no terrain defined osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize(); osg::ref_ptr<SceneUtil::PositionAttitudeTransform> transform (new SceneUtil::PositionAttitudeTransform); transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f)); if (parent) parent->addChild(transform); osg::ref_ptr<osg::Vec3Array> positions (new osg::Vec3Array); osg::ref_ptr<osg::Vec3Array> normals (new osg::Vec3Array); osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array); osg::ref_ptr<osg::VertexBufferObject> vbo (new osg::VertexBufferObject); positions->setVertexBufferObject(vbo); normals->setVertexBufferObject(vbo); colors->setVertexBufferObject(vbo); mStorage->fillVertexBuffers(0, chunkSize, chunkCenter, positions, normals, colors); osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry); geometry->setVertexArray(positions); geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX); geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); geometry->setUseDisplayList(false); geometry->setUseVertexBufferObjects(true); geometry->addPrimitiveSet(mCache.getIndexBuffer(0)); // we already know the bounding box, so no need to let OSG compute it. osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize, -0.5f*mStorage->getCellWorldSize()*chunkSize, minH); osg::Vec3f max (0.5f*mStorage->getCellWorldSize()*chunkSize, 0.5f*mStorage->getCellWorldSize()*chunkSize, maxH); osg::BoundingBox bounds(min, max); geometry->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(bounds)); std::vector<LayerInfo> layerList; std::vector<osg::ref_ptr<osg::Image> > blendmaps; mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList); // For compiling textures, I don't think the osgFX::Effect does it correctly osg::ref_ptr<osg::Node> textureCompileDummy (new osg::Node); std::vector<osg::ref_ptr<osg::Texture2D> > layerTextures; for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it) { layerTextures.push_back(mResourceSystem->getTextureManager()->getTexture2D(it->mDiffuseMap, osg::Texture::REPEAT, osg::Texture::REPEAT)); textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back()); } std::vector<osg::ref_ptr<osg::Texture2D> > blendmapTextures; for (std::vector<osg::ref_ptr<osg::Image> >::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it) { osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D); texture->setImage(*it); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); texture->setResizeNonPowerOfTwoHint(false); blendmapTextures.push_back(texture); textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(0, layerTextures.back()); } // use texture coordinates for both texture units, the layer texture and blend texture for (unsigned int i=0; i<2; ++i) geometry->setTexCoordArray(i, mCache.getUVBuffer()); float blendmapScale = ESM::Land::LAND_TEXTURE_SIZE*chunkSize; osg::ref_ptr<osgFX::Effect> effect (new Terrain::Effect(layerTextures, blendmapTextures, blendmapScale, blendmapScale)); effect->addCullCallback(new SceneUtil::LightListCallback); transform->addChild(effect); #if OSG_VERSION_GREATER_OR_EQUAL(3,3,3) osg::Node* toAttach = geometry.get(); #else osg::ref_ptr<osg::Geode> geode (new osg::Geode); geode->addDrawable(geometry); osg::Node* toAttach = geode.get(); #endif effect->addChild(toAttach); if (mIncrementalCompileOperation) { mIncrementalCompileOperation->add(toAttach); mIncrementalCompileOperation->add(textureCompileDummy); } return transform; } }