void Stroke::draw(Renderer_ptr renderer, uint64_t time) { _shader->setWidth(_width); _shader->setColor(_color); _shader->setStartLength(0.0); _shader->setEndLength(_pathLength); _shader->bind(); // TODO: make this async, instead of tesselating at render-time. if (_dirty) { // TODO: need better LOD calculation. int vertexCount = static_cast<int>(_pathLength); if (vertexCount % 2 == 1) vertexCount++; int triangleCount = (vertexCount - 2) * 2; std::unique_ptr<Vertex[]> vertices(new Vertex[vertexCount]); // TODO: this should be a static Arc function; tesselate(vertices.get(), vertexCount, _path); unique_ptr<grfx::Buffer> vertexBuffer(new grfx::GpuBuffer(renderer, GL_ARRAY_BUFFER)); vertexBuffer->load(std::move(vertices), vertexCount * sizeof(Vertex), GL_STATIC_DRAW); _mesh.reset(new StrokeMesh()); _mesh->setBuffers(std::move(vertexBuffer), Stroke::indexBuffer(renderer, triangleCount), 0, triangleCount); _dirty = false; } _mesh->draw(renderer); }
int main() { vpp::ContextSettings settings = { /* ... */ }; auto window = initWindow(); auto context = vpp::Win32Context(settings, hinstance, window); vpp::VertexBufferLayout vbLayout({vpp::VertexBufferLayout::Point3fColor3f}); vpp::DescriptorSetLayout dsLayout(context.device(), {vk::DescriptorType::UniformBuffer}); vpp::GraphicsPipeline::CreateInfo createInfo; createInfo.renderPass = context.swapChain().vkRenderPass(); createInfo.vertexBufferLayouts = vblayout; createInfo.descriptorSetLayouts = dsLayout; createInfo.shaderProgram = vpp::ShaderProgram({ {vk::ShaderStageFlags::Vertex, "vert.sprv"}, {vk::ShaderStageFlags::Fragment, "frag.sprv"} }); vpp::GraphicsPipeline pipeline(context.device(), createInfo); //buffer, descriptors vpp::Buffer vertexBuffer(context.device(), vertices); vpp::Buffer uniformBuffer(context.device(), someTransformMatrix); vpp::DescriptorSet descriptorSet(dsLayout); static_cast<vpp::BufferDescriptor>(descriptorSet[0]).write(uniformBuffer); //#1 descriptorSet.writeBuffers(0, {uniformBuffer}) //#2; //later pipeline.drawCommands(commandBuffer, {vertexBuffer}, {descriptorSet}); }
//---------------------------------------------------------------------- bool FontManager::Initialise(const glm::ivec2& screenResolution) { this->screenResolution = screenResolution; if (!effect.Load("assets\\effects\\fonteffect.glsl", "RenderFont")) { LOG("did not load font rendering effect\n"); return false; } // Since the screen resolution does not change at runtime, set this now... effect.ScreenSize->Set(glm::vec2(screenResolution)); effect.GlyphTexture->Set(GlyphTextureSlot); sampler = boost::make_shared<Sampler2D>(); sampler->SetMagFilter(GL_LINEAR); sampler->SetMinFilter(GL_LINEAR); sampler->SetWrapS(GL_CLAMP_TO_EDGE); sampler->SetWrapT(GL_CLAMP_TO_EDGE); VertexLayout vertexLayout; vertexLayout.AddAttribute(vertexAttribute); // Initialise vertex buffers for dynamic update... for (size_t i = 0; i < bufferCount; ++i) { boost::shared_ptr<VertexBuffer> vertexBuffer(new VertexBuffer()); vertexBuffer->Initialise(vertexLayout, VerticesInBuffer, GL_DYNAMIC_DRAW); geometry[i].Initialise(vertexBuffer); } return true; }
//[-------------------------------------------------------] //[ Public virtual IApplication methods ] //[-------------------------------------------------------] void FirstTriangle::onInitialization() { // Call the base implementation IApplicationRenderer::onInitialization(); // Get and check the renderer instance Renderer::IRendererPtr renderer(getRenderer()); if (nullptr != renderer) { // Begin debug event RENDERER_BEGIN_DEBUG_EVENT_FUNCTION(renderer) // Decide which shader language should be used (for example "GLSL", "HLSL" or "Cg") Renderer::IShaderLanguagePtr shaderLanguage(renderer->getShaderLanguage()); if (nullptr != shaderLanguage) { { // Create the program // Get the shader source code (outsourced to keep an overview) const char *vertexShaderSourceCode = nullptr; const char *fragmentShaderSourceCode = nullptr; #include "FirstTriangle_Cg.h" #include "FirstTriangle_GLSL_110.h" #include "FirstTriangle_GLSL_ES2.h" #include "FirstTriangle_HLSL_D3D9_D3D10_D3D11.h" #include "FirstTriangle_Null.h" // Create the vertex shader Renderer::IVertexShader *vertexShader = shaderLanguage->createVertexShader(vertexShaderSourceCode); RENDERER_SET_RESOURCE_DEBUG_NAME(vertexShader, "Triangle VS") // Create the fragment shader Renderer::IFragmentShader *fragmentShader = shaderLanguage->createFragmentShader(fragmentShaderSourceCode); RENDERER_SET_RESOURCE_DEBUG_NAME(fragmentShader, "Triangle FS") // Create the program mProgram = shaderLanguage->createProgram(vertexShader, fragmentShader); RENDERER_SET_RESOURCE_DEBUG_NAME(mProgram, "Triangle program") } // Is there a valid program? if (nullptr != mProgram) { // Create the vertex buffer object (VBO) // -> Clip space vertex positions, left/bottom is (-1,-1) and right/top is (1,1) static const float VERTEX_POSITION[] = { // Vertex ID Triangle on screen 0.0f, 1.0f, // 0 0 1.0f, 0.0f, // 1 . . -0.5f, 0.0f // 2 2.......1 }; Renderer::IVertexBufferPtr vertexBuffer(renderer->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferUsage::STATIC_DRAW)); RENDERER_SET_RESOURCE_DEBUG_NAME(vertexBuffer, "Triangle VBO") // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayAttribute vertexArray[] = { { // Attribute 0 // Data destination Renderer::VertexArrayFormat::FLOAT_2, // vertexArrayFormat (Renderer::VertexArrayFormat::Enum) "Position", // name[64] (char) "POSITION", // semantic[64] (char) 0, // semanticIndex (unsigned int) // Data source vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) 0, // offset (unsigned int) sizeof(float) * 2, // stride (unsigned int) // Data source, instancing part 0 // instancesPerElement (unsigned int) } }; mVertexArray = mProgram->createVertexArray(sizeof(vertexArray) / sizeof(Renderer::VertexArrayAttribute), vertexArray); RENDERER_SET_RESOURCE_DEBUG_NAME(mVertexArray, "Triangle VAO") } }
//[-------------------------------------------------------] //[ Public virtual IApplication methods ] //[-------------------------------------------------------] void FirstGeometryShader::onInitialization() { // Call the base implementation IApplicationRenderer::onInitialization(); // Get and check the renderer instance // -> Geometry shaders supported? Renderer::IRendererPtr renderer(getRenderer()); if (nullptr != renderer && renderer->getCapabilities().maximumNumberOfGsOutputVertices) { // Begin debug event RENDERER_BEGIN_DEBUG_EVENT_FUNCTION(renderer) // Decide which shader language should be used (for example "GLSL", "HLSL" or "Cg") Renderer::IShaderLanguagePtr shaderLanguage(renderer->getShaderLanguage()); if (nullptr != shaderLanguage) { { // Create the program // Get the shader source code (outsourced to keep an overview) const char *vertexShaderSourceCode = nullptr; const char *geometryShaderSourceCode = nullptr; const char *fragmentShaderSourceCode = nullptr; #include "FirstGeometryShader_GLSL_330.h" #include "FirstGeometryShader_HLSL_D3D10_D3D11.h" #include "FirstGeometryShader_Null.h" // Create the program mProgram = shaderLanguage->createProgram( shaderLanguage->createVertexShader(vertexShaderSourceCode), shaderLanguage->createGeometryShader(geometryShaderSourceCode, Renderer::GsInputPrimitiveTopology::POINTS, Renderer::GsOutputPrimitiveTopology::TRIANGLE_STRIP, 3), shaderLanguage->createFragmentShader(fragmentShaderSourceCode)); } // TODO(co) Attribute less rendering (aka "drawing without data") possible with OpenGL? For me it appears not to work, I see nothing and also get no error... // -> Tested with: "Radeon HD 6970M", driver "catalyst_12-7_beta_windows7_20120629.exe" // -> According to http://renderingpipeline.com/2012/03/are-vertex-shaders-obsolete/ it should work // -> Apparently there are currently some issues when using this approach: http://www.opengl.org/discussion_boards/showthread.php/177372-Rendering-simple-shapes-without-passing-vertices if (nullptr != mProgram && 0 == strcmp(renderer->getName(), "OpenGL")) { // Create the vertex buffer object (VBO) static const float VERTEX_POSITION[] = { // Vertex ID 42.0f // 0 }; Renderer::IVertexBufferPtr vertexBuffer(renderer->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferUsage::STATIC_DRAW)); // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayAttribute vertexArray[] = { { // Attribute 0 // Data destination Renderer::VertexArrayFormat::FLOAT_1, // vertexArrayFormat (Renderer::VertexArrayFormat::Enum) "Position", // name[64] (char) "POSITION", // semantic[64] (char) 0, // semanticIndex (unsigned int) // Data source vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) 0, // offset (unsigned int) sizeof(float), // stride (unsigned int) // Data source, instancing part 0 // instancesPerElement (unsigned int) } }; mVertexArray = mProgram->createVertexArray(sizeof(vertexArray) / sizeof(Renderer::VertexArrayAttribute), vertexArray); } } // End debug event RENDERER_END_DEBUG_EVENT(renderer) }
//[-------------------------------------------------------] //[ Public virtual IApplication methods ] //[-------------------------------------------------------] void Fxaa::onInitialization() { // Call the base implementation IApplicationRenderer::onInitialization(); // Get and check the renderer instance Renderer::IRendererPtr renderer(getRenderer()); if (nullptr != renderer) { // Begin debug event RENDERER_BEGIN_DEBUG_EVENT_FUNCTION(renderer) // Create the framebuffer object (FBO) instance by using the current window size recreateFramebuffer(); { // Create sampler state // -> Our texture does not have any mipmaps, set "Renderer::SamplerState::maxLOD" to zero // in order to ensure a correct behaviour across the difference graphics APIs // -> When not doing this you usually have no issues when using OpenGL, OpenGL ES 2, Direct 10, // Direct3D 11 or Direct3D 9 with the "ps_2_0"-profile, but when using Direct3D 9 with the // "ps_3_0"-profile you might get into trouble due to another internal graphics API behaviour Renderer::SamplerState samplerState = Renderer::ISamplerState::getDefaultSamplerState(); samplerState.maxLOD = 0.0f; // We don't use mipmaps mSamplerState = renderer->createSamplerState(samplerState); } { // Depth stencil state // -> By default depth test is enabled // -> In this simple example we don't need depth test, so, disable it so we don't need to care about the depth buffer // Create depth stencil state Renderer::DepthStencilState depthStencilState = Renderer::IDepthStencilState::getDefaultDepthStencilState(); depthStencilState.depthEnable = false; mDepthStencilState = renderer->createDepthStencilState(depthStencilState); // Set the depth stencil state directly within this initialization phase, we don't change it later on renderer->omSetDepthStencilState(mDepthStencilState); } // Decide which shader language should be used (for example "GLSL", "HLSL" or "Cg") Renderer::IShaderLanguagePtr shaderLanguage(renderer->getShaderLanguage()); if (nullptr != shaderLanguage) { { // Create the program for scene rendering // Get the shader source code (outsourced to keep an overview) const char *vertexShaderSourceCode = nullptr; const char *fragmentShaderSourceCode = nullptr; #include "Fxaa_SceneRendering_Cg.h" #include "Fxaa_SceneRendering_GLSL_120.h" #include "Fxaa_SceneRendering_GLSL_ES2.h" #include "Fxaa_SceneRendering_HLSL_D3D9_D3D10_D3D11.h" #include "Fxaa_SceneRendering_Null.h" // Create the program for scene rendering mProgramSceneRendering = shaderLanguage->createProgram(shaderLanguage->createVertexShader(vertexShaderSourceCode), shaderLanguage->createFragmentShader(fragmentShaderSourceCode)); } // Is there a valid program for scene rendering? if (nullptr != mProgramSceneRendering) { // Create the vertex buffer object (VBO) // -> Clip space vertex positions, left/bottom is (-1,-1) and right/top is (1,1) static const float VERTEX_POSITION[] = { // Vertex ID Triangle on screen 0.0f, 1.0f, // 0 0 1.0f, 0.0f, // 1 . . -0.5f, 0.0f // 2 2.......1 }; Renderer::IVertexBufferPtr vertexBuffer(renderer->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferUsage::STATIC_DRAW)); // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayAttribute vertexArray[] = { { // Attribute 0 // Data destination Renderer::VertexArrayFormat::FLOAT_2, // vertexArrayFormat (Renderer::VertexArrayFormat::Enum) "Position", // name[64] (char) "POSITION", // semantic[64] (char) 0, // semanticIndex (unsigned int) // Data source vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) 0, // offset (unsigned int) sizeof(float) * 2, // stride (unsigned int) // Data source, instancing part 0 // instancesPerElement (unsigned int) } }; mVertexArraySceneRendering = mProgramSceneRendering->createVertexArray(sizeof(vertexArray) / sizeof(Renderer::VertexArrayAttribute), vertexArray); } // Create the post-processing program instance by using the current window size recreatePostProcessingProgram(); // Is there a valid program for post-processing? if (nullptr != mProgramPostProcessing) { // Create the vertex buffer object (VBO) // -> Clip space vertex positions, left/bottom is (-1,-1) and right/top is (1,1) static const float VERTEX_POSITION[] = { // Vertex ID Triangle strip on screen -1.0f, -1.0f, // 0 1.......3 -1.0f, 1.0f, // 1 . . . 1.0f, -1.0f, // 2 0.......2 1.0f, 1.0f // 3 }; Renderer::IVertexBufferPtr vertexBuffer(renderer->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferUsage::STATIC_DRAW)); // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayAttribute vertexArray[] = { { // Attribute 0 // Data destination Renderer::VertexArrayFormat::FLOAT_2, // vertexArrayFormat (Renderer::VertexArrayFormat::Enum) "Position", // name[64] (char) "POSITION", // semantic[64] (char) 0, // semanticIndex (unsigned int) // Data source vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) 0, // offset (unsigned int) sizeof(float) * 2, // stride (unsigned int) // Data source, instancing part 0 // instancesPerElement (unsigned int) } }; mVertexArrayPostProcessing = mProgramSceneRendering->createVertexArray(sizeof(vertexArray) / sizeof(Renderer::VertexArrayAttribute), vertexArray); } } // End debug event RENDERER_END_DEBUG_EVENT(renderer) }
void loadMeshes( CalCoreModel* calCoreModel, MeshesVector& meshes ) throw (std::runtime_error) { const int maxVertices = Constants::MAX_VERTEX_PER_MODEL; const int maxFaces = Constants::MAX_VERTEX_PER_MODEL * 3; std::auto_ptr< CalHardwareModel > calHardwareModel( new CalHardwareModel( calCoreModel ) ); osg::ref_ptr< VertexBuffer > vertexBuffer( new VertexBuffer( maxVertices ) ); osg::ref_ptr< WeightBuffer > weightBuffer( new WeightBuffer( maxVertices ) ); osg::ref_ptr< MatrixIndexBuffer > matrixIndexBuffer( new MatrixIndexBuffer( maxVertices ) ); osg::ref_ptr< NormalBuffer > normalBuffer( new NormalBuffer( maxVertices ) ); osg::ref_ptr< NormalBuffer > tangentBuffer( new NormalBuffer( maxVertices ) ); osg::ref_ptr< NormalBuffer > binormalBuffer( new NormalBuffer( maxVertices ) ); osg::ref_ptr< TexCoordBuffer > texCoordBuffer( new TexCoordBuffer( maxVertices ) ); std::vector< CalIndex > indexBuffer( maxFaces*3 ); std::vector< float > floatMatrixIndexBuffer( maxVertices*4 ); calHardwareModel->setVertexBuffer((char*)vertexBuffer->getDataPointer(), 3*sizeof(float)); #ifdef OSG_CAL_BYTE_BUFFERS std::vector< float > floatNormalBuffer( getVertexCount()*3 ); calHardwareModel->setNormalBuffer((char*)&floatNormalBuffer.begin(), 3*sizeof(float)); #else calHardwareModel->setNormalBuffer((char*)normalBuffer->getDataPointer(), 3*sizeof(float)); #endif calHardwareModel->setWeightBuffer((char*)weightBuffer->getDataPointer(), 4*sizeof(float)); calHardwareModel->setMatrixIndexBuffer((char*)&floatMatrixIndexBuffer.front(), 4*sizeof(float)); calHardwareModel->setTextureCoordNum( 1 ); calHardwareModel->setTextureCoordBuffer(0, // texture stage # (char*)texCoordBuffer->getDataPointer(), 2*sizeof(float)); calHardwareModel->setIndexBuffer( &indexBuffer.front() ); // calHardwareModel->setCoreMeshIds(_activeMeshes); // if ids not set all meshes will be used at load() time //std::cout << "calHardwareModel->load" << std::endl; calHardwareModel->load( 0, 0, Constants::MAX_BONES_PER_MESH ); //std::cout << "calHardwareModel->load ok" << std::endl; int vertexCount = calHardwareModel->getTotalVertexCount(); // int faceCount = calHardwareModel->getTotalFaceCount(); // std::cout << "vertexCount = " << vertexCount << "; faceCount = " << faceCount << std::endl; GLubyte* matrixIndexBufferData = (GLubyte*) matrixIndexBuffer->getDataPointer(); for ( int i = 0; i < vertexCount*4; i++ ) { matrixIndexBufferData[i] = static_cast< GLubyte >( floatMatrixIndexBuffer[i] ); } #ifdef OSG_CAL_BYTE_BUFFERS GLbyte* normals = (GLbyte*) normalBuffer->getDataPointer(); for ( int i = 0; i < vertexCount*3; i++ ) { normals[i] = static_cast< GLbyte >( floatNormalBuffer[i]*127.0 ); } #endif // invert UVs for OpenGL (textures are inverted otherwise - for example, see abdulla/klinok) GLfloat* texCoordBufferData = (GLfloat*) texCoordBuffer->getDataPointer(); for ( float* tcy = texCoordBufferData + 1; tcy < texCoordBufferData + 2*vertexCount; tcy += 2 ) { *tcy = 1.0f - *tcy; } // -- And now create meshes data -- int unriggedBoneIndex = calCoreModel->getCoreSkeleton()->getVectorCoreBone().size(); // we add empty bone in ModelData to handle unrigged vertices; for( int hardwareMeshId = 0; hardwareMeshId < calHardwareModel->getHardwareMeshCount(); hardwareMeshId++ ) { calHardwareModel->selectHardwareMesh(hardwareMeshId); int faceCount = calHardwareModel->getFaceCount(); if ( faceCount == 0 ) { continue; // we ignore empty meshes } CalHardwareModel::CalHardwareMesh* hardwareMesh = &calHardwareModel->getVectorHardwareMesh()[ hardwareMeshId ]; osg::ref_ptr< MeshData > m( new MeshData ); m->name = calCoreModel->getCoreMesh( hardwareMesh->meshId )->getName(); m->coreMaterial = hardwareMesh->pCoreMaterial; if ( m->coreMaterial == NULL ) { CalCoreMesh* coreMesh = calCoreModel->getCoreMesh( hardwareMesh->meshId ); CalCoreSubmesh* coreSubmesh = coreMesh->getCoreSubmesh( hardwareMesh->submeshId ); // hardwareMesh->pCoreMaterial = // coreModel->getCoreMaterial( coreSubmesh->getCoreMaterialThreadId() ); char buf[ 1024 ]; snprintf( buf, 1024, "pCoreMaterial == NULL for mesh '%s' (mesh material id = %d), verify your mesh file data", m->name.c_str(), coreSubmesh->getCoreMaterialThreadId() ); throw std::runtime_error( buf ); } // -- Create index buffer -- int indexesCount = faceCount * 3; int startIndex = calHardwareModel->getStartIndex(); if ( indexesCount <= 0x100 ) { m->indexBuffer = new osg::DrawElementsUByte( osg::PrimitiveSet::TRIANGLES, indexesCount ); GLubyte* data = (GLubyte*)m->indexBuffer->getDataPointer(); const CalIndex* i = &indexBuffer[ startIndex ]; const CalIndex* iEnd = &indexBuffer[ startIndex + indexesCount ]; while ( i < iEnd ) { *data++ = (GLubyte)*i++; } } else if ( indexesCount <= 0x10000 ) { m->indexBuffer = new osg::DrawElementsUShort( osg::PrimitiveSet::TRIANGLES, indexesCount ); GLushort* data = (GLushort*)m->indexBuffer->getDataPointer(); const CalIndex* i = &indexBuffer[ startIndex ]; const CalIndex* iEnd = &indexBuffer[ startIndex + indexesCount ]; while ( i < iEnd ) { *data++ = (GLushort)*i++; } } else { m->indexBuffer = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, indexesCount ); GLuint* data = (GLuint*)m->indexBuffer->getDataPointer(); const CalIndex* i = &indexBuffer[ startIndex ]; const CalIndex* iEnd = &indexBuffer[ startIndex + indexesCount ]; while ( i < iEnd ) { *data++ = (GLuint)*i++; } } // -- Create other buffers -- int vertexCount = calHardwareModel->getVertexCount(); int baseVertexIndex = calHardwareModel->getBaseVertexIndex(); #define SUB_BUFFER( _type, _name ) \ new _type( _name->begin() + baseVertexIndex, \ _name->begin() + baseVertexIndex + vertexCount ) m->vertexBuffer = SUB_BUFFER( VertexBuffer, vertexBuffer ); m->weightBuffer = SUB_BUFFER( WeightBuffer, weightBuffer ); m->matrixIndexBuffer = SUB_BUFFER( MatrixIndexBuffer, matrixIndexBuffer ); m->normalBuffer = SUB_BUFFER( NormalBuffer, normalBuffer ); m->texCoordBuffer = SUB_BUFFER( TexCoordBuffer, texCoordBuffer ); // -- Parameters and buffers setup -- m->boundingBox = calculateBoundingBox( m->vertexBuffer.get() ); m->bonesIndices = hardwareMesh->m_vectorBonesIndices; checkRigidness( m.get(), unriggedBoneIndex ); checkForEmptyTexCoord( m.get() ); generateTangentAndHandednessBuffer( m.get(), &indexBuffer[ startIndex ] ); meshes.push_back( m.get() ); } }
//------------------------------------------------------------------------------ static void createVtrMesh(Shape * shape, int maxlevel) { Stopwatch s; s.Start(); // create Vtr mesh (topology) OpenSubdiv::Sdc::Type sdctype = GetSdcType(*shape); OpenSubdiv::Sdc::Options sdcoptions = GetSdcOptions(*shape); OpenSubdiv::Far::TopologyRefiner * refiner = OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Create(sdctype, sdcoptions, *shape); OpenSubdiv::Far::PatchTables * patchTables = 0; if (g_Adaptive) { refiner->RefineAdaptive(maxlevel, /*fullTopology*/true); patchTables = OpenSubdiv::Far::PatchTablesFactory::Create(*refiner); g_numPatches = patchTables->GetNumPatches(); } else { refiner->RefineUniform(maxlevel, /*fullTopology*/true); } s.Stop(); // create vertex primvar data buffer std::vector<Vertex> vertexBuffer(refiner->GetNumVerticesTotal()); Vertex * verts = &vertexBuffer[0]; //printf("Vtr time: %f ms (topology)\n", float(s.GetElapsed())*1000.0f); // copy coarse vertices positions int ncoarseverts = shape->GetNumVertices(); for (int i=0; i<ncoarseverts; ++i) { float * ptr = &shape->verts[i*3]; verts[i].SetPosition(ptr[0], ptr[1], ptr[2]); } //#define no_stencils #ifdef no_stencils { s.Start(); // populate buffer with Vtr interpolated vertex data refiner->Interpolate(verts, verts + ncoarseverts); s.Stop(); //printf(" %f ms (interpolate)\n", float(s.GetElapsed())*1000.0f); //printf(" %f ms (total)\n", float(s.GetTotalElapsed())*1000.0f); } #else { OpenSubdiv::Far::StencilTablesFactory::Options options; options.generateOffsets=true; options.generateAllLevels=true; options.sortBySize=false; OpenSubdiv::Far::StencilTables const * stencilTables = OpenSubdiv::Far::StencilTablesFactory::Create(*refiner, options); stencilTables->UpdateValues(verts, verts + ncoarseverts); } #endif if (g_VtrDrawVertIDs) { createVertNumbers(*refiner, vertexBuffer); } if (g_VtrDrawFaceIDs) { createFaceNumbers(*refiner, vertexBuffer); } if (g_VtrDrawPtexIDs and patchTables) { createPtexNumbers(*patchTables, vertexBuffer); } if (g_Adaptive and patchTables) { createPatchNumbers(*patchTables, vertexBuffer); } createEdgeNumbers(*refiner, vertexBuffer, g_VtrDrawEdgeIDs!=0, g_VtrDrawEdgeSharpness!=0); GLMesh::Options options; options.vertColorMode=g_Adaptive ? GLMesh::VERTCOLOR_BY_LEVEL : GLMesh::VERTCOLOR_BY_SHARPNESS; options.edgeColorMode=g_Adaptive ? GLMesh::EDGECOLOR_BY_PATCHTYPE : GLMesh::EDGECOLOR_BY_SHARPNESS; options.faceColorMode=g_Adaptive ? GLMesh::FACECOLOR_BY_PATCHTYPE :GLMesh::FACECOLOR_SOLID; if (g_Adaptive) { g_vtr_glmesh.Initialize(options, *refiner, patchTables, (float *)&verts[0]); g_vtr_glmesh.SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); } else { g_vtr_glmesh.Initialize(options, *refiner, patchTables, (float *)&verts[0]); g_vtr_glmesh.SetDiffuseColor(0.75f, 0.9f, 1.0f, 1.0f); } //setFaceColors(*refiner); g_vtr_glmesh.InitializeDeviceBuffers(); delete refiner; delete patchTables; }
//[-------------------------------------------------------] //[ Public virtual IApplication methods ] //[-------------------------------------------------------] void FirstGeometryShader::onInitialization() { // Call the base implementation IApplicationRenderer::onInitialization(); // Get and check the renderer instance // -> Geometry shaders supported? Renderer::IRendererPtr renderer(getRenderer()); if (nullptr != renderer && renderer->getCapabilities().maximumNumberOfGsOutputVertices) { // Create the buffer manager mBufferManager = renderer->createBufferManager(); { // Create the root signature // Setup Renderer::RootSignatureBuilder rootSignature; rootSignature.initialize(0, nullptr, 0, nullptr, Renderer::RootSignatureFlags::ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); // Create the instance mRootSignature = renderer->createRootSignature(rootSignature); } // Vertex input layout const Renderer::VertexAttribute vertexAttributesLayout[] = { { // Attribute 0 // Data destination Renderer::VertexAttributeFormat::FLOAT_1, // vertexAttributeFormat (Renderer::VertexAttributeFormat) "Position", // name[32] (char) "POSITION", // semanticName[32] (char) 0, // semanticIndex (uint32_t) // Data source 0, // inputSlot (uint32_t) 0, // alignedByteOffset (uint32_t) // Data source, instancing part 0 // instancesPerElement (uint32_t) } }; const Renderer::VertexAttributes vertexAttributes(glm::countof(vertexAttributesLayout), vertexAttributesLayout); { // Create vertex array object (VAO) // Create the vertex buffer object (VBO) static const float VERTEX_POSITION[] = { // Vertex ID 42.0f // 0 }; Renderer::IVertexBufferPtr vertexBuffer(mBufferManager->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferUsage::STATIC_DRAW)); // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayVertexBuffer vertexArrayVertexBuffers[] = { { // Vertex buffer 0 vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) sizeof(float) // strideInBytes (uint32_t) } }; mVertexArray = mBufferManager->createVertexArray(vertexAttributes, glm::countof(vertexArrayVertexBuffers), vertexArrayVertexBuffers); } // Create the program: Decide which shader language should be used (for example "GLSL" or "HLSL") Renderer::IShaderLanguagePtr shaderLanguage(renderer->getShaderLanguage()); if (nullptr != shaderLanguage) { // Create the program Renderer::IProgramPtr program; { // Get the shader source code (outsourced to keep an overview) const char *vertexShaderSourceCode = nullptr; const char *geometryShaderSourceCode = nullptr; const char *fragmentShaderSourceCode = nullptr; #include "FirstGeometryShader_GLSL_410.h" #include "FirstGeometryShader_HLSL_D3D10_D3D11_D3D12.h" #include "FirstGeometryShader_Null.h" // Create the program program = shaderLanguage->createProgram( *mRootSignature, vertexAttributes, shaderLanguage->createVertexShaderFromSourceCode(vertexAttributes, vertexShaderSourceCode), shaderLanguage->createGeometryShaderFromSourceCode(geometryShaderSourceCode, Renderer::GsInputPrimitiveTopology::POINTS, Renderer::GsOutputPrimitiveTopology::TRIANGLE_STRIP, 3), shaderLanguage->createFragmentShaderFromSourceCode(fragmentShaderSourceCode)); } // Create the pipeline state object (PSO) if (nullptr != program) { Renderer::PipelineState pipelineState = Renderer::PipelineStateBuilder(mRootSignature, program, vertexAttributes); pipelineState.primitiveTopologyType = Renderer::PrimitiveTopologyType::POINT; mPipelineState = renderer->createPipelineState(pipelineState); } } // Since we're always submitting the same commands to the renderer, we can fill the command buffer once during initialization and then reuse it multiple times during runtime fillCommandBuffer(); } }
void Renderer2::GenerateRoomBuffer() { float h = 4.0f * m_surfaceSize.y / m_surfaceSize.x; vec3 roomVertices[] = { {-2.0f, -h / 2.0f, -4.0f}, {2.0f, -h / 2.0f, -4.0f}, {2.0f, h / 2.0f, -4.0f}, {-2.0f, h / 2.0f, -4.0f}, {-2.0f, -h / 2.0f, -10.0f}, {2.0f, -h / 2.0f, -10.0f}, {2.0f, h / 2.0f, -10.0f}, {-2.0f, h / 2.0f, -10.0f} }; GLushort roomIndices[] = { 0, 4, 3, 7, 3, 4, 4, 5, 7, 6, 7, 5, 1, 2, 5, 6, 5, 2, 6, 2, 7, 3, 7, 2, 0, 1, 4, 5, 4, 1 }; m_roomVertexCount = sizeof(roomIndices) / sizeof(roomIndices[0]); vector<RoomVertex> vertexBuffer(m_roomVertexCount); for (int i = 0; i < m_roomVertexCount; i += 3) { GLushort c = roomIndices[i]; GLushort r = roomIndices[i + 1]; GLushort l = roomIndices[i + 2]; vec3 centerVertex = roomVertices[c]; vec3 rightVertex = roomVertices[r]; vec3 leftVertex = roomVertices[l]; vec3 a(rightVertex.x - centerVertex.x, rightVertex.y - centerVertex.y, rightVertex.z - centerVertex.z); vec3 b(leftVertex.x - centerVertex.x, leftVertex.y - centerVertex.y, leftVertex.z - centerVertex.z); vec3 normal = a.Cross(b).Normalized(); vertexBuffer[i].Position = centerVertex; vertexBuffer[i + 1].Position = rightVertex; vertexBuffer[i + 2].Position = leftVertex; vertexBuffer[i].Normal = normal; vertexBuffer[i + 1].Normal = normal; vertexBuffer[i + 2].Normal = normal; } glGenBuffers(1, &m_roomVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, m_roomVertexBuffer); glBufferData(GL_ARRAY_BUFFER, vertexBuffer.size() * sizeof(RoomVertex), &vertexBuffer[0], GL_STATIC_DRAW); }
bool Console::draw() { int windowHeight = Ego::GraphicsSystem::window->getSize().height(); if (!windowHeight || !this->on) { return false; } SDL_Rect *pwin = &(this->rect); auto& renderer = Renderer::get(); renderer.getTextureUnit().setActivated(nullptr); // The colour white. static const auto white = Math::Colour4f::white(); // The colour black. static const auto black = Math::Colour4f::black(); // The vertex data structure and the vertex descriptor. struct Vertex { float x, y; }; static const Ego::VertexDescriptor vertexDescriptor({Ego::VertexElementDescriptor(0, Ego::VertexElementDescriptor::Syntax::F2, Ego::VertexElementDescriptor::Semantics::Position)}); renderer.setColour(white); renderer.setLineWidth(5); Ego::VertexBuffer vertexBuffer(4, vertexDescriptor); { Ego::BufferScopedLock lock(vertexBuffer); Vertex *vertex = lock.get<Vertex>(); vertex->x = pwin->x; vertex->y = pwin->y; ++vertex; vertex->x = pwin->x + pwin->w; vertex->y = pwin->y; ++vertex; vertex->x = pwin->x + pwin->w; vertex->y = pwin->y + pwin->h; ++vertex; vertex->x = pwin->x; vertex->y = pwin->y + pwin->h; } renderer.render(vertexBuffer, Ego::PrimitiveType::LineLoop, 0, 4); renderer.setLineWidth(1); renderer.setColour(black); renderer.render(vertexBuffer, Ego::PrimitiveType::Quadriliterals, 0, 4); { Ego::OpenGL::PushAttrib pa(GL_SCISSOR_BIT | GL_ENABLE_BIT); { int textWidth, textHeight, height; // clip the viewport renderer.setScissorTestEnabled(true); renderer.setScissorRectangle(pwin->x, windowHeight - (pwin->y + pwin->h), pwin->w, pwin->h); height = pwin->h; char buffer[ConsoleSettings::InputSettings::Length]; // draw the current command line sprintf(buffer, "%s ", ConsoleSettings::InputSettings::Prompt.c_str()); strncat(buffer, this->buffer, 1022); buffer[1022] = CSTR_END; this->pfont->getTextSize(buffer, &textWidth, &textHeight); height -= textHeight; this->pfont->drawText(buffer, pwin->x, height - textHeight, white); if (CSTR_END != this->output_buffer[0]) { // grab the line offsets size_t console_line_count = 0; size_t console_line_offsets[1024]; size_t console_line_lengths[1024]; char *pstr = this->output_buffer; while (pstr) { size_t len = strcspn(pstr, "\n"); console_line_offsets[console_line_count] = pstr - this->output_buffer; console_line_lengths[console_line_count] = len; if (0 == len) { break; } pstr += len + 1; console_line_count++; } // draw the last output line and work backwards for (size_t i = console_line_count; i >= 1 && height > 0; --i) { size_t j = i - 1; size_t len = std::min((size_t)1023, console_line_lengths[j]); strncpy(buffer, this->output_buffer + console_line_offsets[j], len); buffer[len] = CSTR_END; this->pfont->getTextSize(buffer, &textWidth, &textHeight); height -= textHeight; this->pfont->drawText(buffer, pwin->x, height - textHeight, white); } } } } return true; }
int main() { // first, create a vulkan instance // the needed/used instance extensions constexpr const char* iniExtensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_EXTENSION_NAME }; // enables all default layers constexpr auto layer = "VK_LAYER_LUNARG_standard_validation"; // basic application info // we use vulkan api version 1.0 vk::ApplicationInfo appInfo ("vpp-intro", 1, "vpp", 1, VK_API_VERSION_1_0); vk::InstanceCreateInfo instanceInfo; instanceInfo.pApplicationInfo = &appInfo; instanceInfo.enabledExtensionCount = sizeof(iniExtensions) / sizeof(iniExtensions[0]); instanceInfo.ppEnabledExtensionNames = iniExtensions; instanceInfo.enabledLayerCount = 1; instanceInfo.ppEnabledLayerNames = &layer; vpp::Instance instance(instanceInfo); // create a debug callback for our instance and the default layers // the default implementation will just output to std::cerr when a debug callback // is received vpp::DebugCallback debugCallback(instance); // this function will create a winapi window wrapper and also create a surface for it // this should usually be done by a cross platform window abstraction Window window(instance); // now create a device for the instance and surface // note how vpp will automatically select a suited physical device and query // queue families to create basic-needs queues with this constructor. // We also retrieve the present queue to present on our surface from this // constructor const vpp::Queue* presentQueue; vpp::Device device(instance, window.surface, presentQueue); // now we can create a vulkan swapchain // again, we just use the fast way that choses quite sane defaults for us but note // that the class offers many convininient configuration possibilities vpp::Swapchain swapchain(device, window.surface); // to render the triangle we also need to create a render pass vpp::RenderPass renderPass = createRenderPass(swapchain); // we also create the graphics pipeline that will render our triangle as well // as the buffer to hold our vertices vpp::PipelineLayout pipelineLayout(device, {}); auto pipeline = createGraphicsPipeline(device, renderPass, pipelineLayout); // note how vpp takes care of buffer allocation (in an efficient way, even when used // for multiple resources) constexpr auto size = 3u * (2u + 4u) * 4u; // 3 vertices, vec2, vec4 with 4 bytes components constexpr auto usage = vk::BufferUsageBits::vertexBuffer | vk::BufferUsageBits::transferDst; vpp::Buffer vertexBuffer(device, {{}, size, usage}); // vertex data (only positions and color) constexpr std::array<float, 6 * 3> vertexData = {{ 0.f, -0.75f, 1.f, 0.f, 0.f, 1.f, // top -0.75f, 0.75f, 0.f, 1.f, 0.f, 1.f, // left 0.75f, 0.75f, 0.f, 0.f, 1.f, 1.f // right }}; // vpp can now be used to fill the vertex buffer with data in the most efficient way // in this case the buffer layout does not matter since its a vertex buffer // note how vpp automatically unpacks the std::array vpp::fill140(vertexBuffer, vpp::raw(vertexData)); // to render onto the created swapchain we can use vpp::SwapchainRenderer // the class implements the default framebuffer and commandbuffer handling // we simply implement the vpp::RendererBuilder interface that will be used // to build the render command buffers vpp::SwapchainRenderer::CreateInfo rendererInfo; rendererInfo.queueFamily = device.queue(vk::QueueBits::graphics)->family(); rendererInfo.renderPass = renderPass; auto impl = std::make_unique<IntroRendererImpl>(); impl->pipeline = pipeline; impl->vertexBuffer = vertexBuffer; vpp::SwapchainRenderer renderer(swapchain, rendererInfo, std::move(impl)); renderer.record(); // run the main loop // we just recevie windows events and render after all are processed // sry for windows again... using Clock = std::chrono::high_resolution_clock; auto frames = 0u; auto point = Clock::now(); auto run = true; while(run) { MSG msg; while(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != 0) { if(msg.message == WM_QUIT) { run = false; break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } if(!run) break; renderer.renderBlock(*presentQueue); ++frames; // output the average fps count ever second auto duration = Clock::now() - point; if(duration >= std::chrono::seconds(1)) { auto count = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); std::cout << static_cast<int>(frames * (1000.0 / count)) << " fps\n"; point = Clock::now(); frames = 0u; } } return EXIT_SUCCESS; }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] CubeRendererDrawInstanced::CubeRendererDrawInstanced(Renderer::IRenderer &renderer, unsigned int numberOfTextures, unsigned int sceneRadius) : mRenderer(&renderer), mNumberOfTextures(numberOfTextures), mSceneRadius(sceneRadius), mMaximumNumberOfInstancesPerBatch(0), mNumberOfBatches(0), mBatches(nullptr) { // Begin debug event RENDERER_BEGIN_DEBUG_EVENT_FUNCTION(&renderer) // Check number of textures (limit of this implementation and renderer limit) if (mNumberOfTextures > MAXIMUM_NUMBER_OF_TEXTURES) { mNumberOfTextures = MAXIMUM_NUMBER_OF_TEXTURES; } if (mNumberOfTextures > mRenderer->getCapabilities().maximumNumberOf2DTextureArraySlices) { mNumberOfTextures = mRenderer->getCapabilities().maximumNumberOf2DTextureArraySlices; } // Get the maximum number of instances per batch // -> In this application, this depends on the maximum texture buffer size // -> /2 -> One instance requires two texels mMaximumNumberOfInstancesPerBatch = mRenderer->getCapabilities().maximumTextureBufferSize / 2; { // Create the textures static const unsigned int TEXTURE_WIDTH = 128; static const unsigned int TEXTURE_HEIGHT = 128; static const unsigned int NUMBER_OF_BYTES = TEXTURE_WIDTH * TEXTURE_HEIGHT * 4; // Allocate memory for the 2D texture array unsigned char *data = new unsigned char[NUMBER_OF_BYTES * mNumberOfTextures]; { // Fill the texture content // TODO(co) Be a little bit more creative while filling the texture data unsigned char *dataCurrent = data; const float colors[][MAXIMUM_NUMBER_OF_TEXTURES] = { { 1.0f, 0.0f, 0.0f}, { 0.0f, 0.1f, 0.0f}, { 0.0f, 0.0f, 0.1f}, { 0.5f, 0.5f, 0.5f}, { 1.0f, 1.0f, 1.0f}, { 0.1f, 0.2f, 0.2f}, { 0.2f, 0.5f, 0.5f}, { 0.1f, 0.8f, 0.2f} }; for (unsigned int j = 0; j < mNumberOfTextures; ++j) { // Random content for (unsigned int i = 0; i < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++i) { *dataCurrent = static_cast<unsigned char>((rand() % 255) * colors[j][0]); ++dataCurrent; *dataCurrent = static_cast<unsigned char>((rand() % 255) * colors[j][1]); ++dataCurrent; *dataCurrent = static_cast<unsigned char>((rand() % 255) * colors[j][2]); ++dataCurrent; *dataCurrent = 255; ++dataCurrent; } } } // Create the texture instance // -> By using 2D array textures together with OpenGL/Direct3D 11 instancing we get a handy implementation // -> This limits of course the cross platform support, fallback solutions might be a good idea in productive code // -> A fallback is not really required in our example situation because we're using draw instanced which already requires a more modern graphics card mTexture2DArray = mRenderer->createTexture2DArray(TEXTURE_WIDTH, TEXTURE_HEIGHT, mNumberOfTextures, Renderer::TextureFormat::R8G8B8A8, data, Renderer::TextureFlag::MIPMAPS); // Free texture memory delete [] data; } // Create sampler state mSamplerState = mRenderer->createSamplerState(Renderer::ISamplerState::getDefaultSamplerState()); // Decide which shader language should be used (for example "GLSL", "HLSL" or "Cg") Renderer::IShaderLanguagePtr shaderLanguage(mRenderer->getShaderLanguage()); if (nullptr != shaderLanguage) { // Uniform buffer object (UBO, "constant buffer" in Direct3D terminology) supported? // -> If they are there, we really want to use them (performance and ease of use) if (mRenderer->getCapabilities().uniformBuffer) { { // Create and set constant program uniform buffer at once // TODO(co) Uggly fixed hacked in model-view-projection matrix // TODO(co) OpenGL matrix, Direct3D has minor differences within the projection matrix we have to compensate static const float MVP[] = { 1.2803299f, -0.97915620f, -0.58038759f, -0.57922798f, 0.0f, 1.9776078f, -0.57472473f, -0.573576453f, -1.2803299f, -0.97915620f, -0.58038759f, -0.57922798f, 0.0f, 0.0f, 9.8198195f, 10.0f }; mUniformBufferStaticVs = shaderLanguage->createUniformBuffer(sizeof(MVP), MVP, Renderer::BufferUsage::STATIC_DRAW); } // Create dynamic uniform buffers mUniformBufferDynamicVs = shaderLanguage->createUniformBuffer(sizeof(float) * 2, nullptr, Renderer::BufferUsage::DYNAMIC_DRAW); mUniformBufferDynamicFs = shaderLanguage->createUniformBuffer(sizeof(float) * 3, nullptr, Renderer::BufferUsage::DYNAMIC_DRAW); } { // Create the program // Get the shader source code (outsourced to keep an overview) const char *vertexShaderSourceCode = nullptr; const char *fragmentShaderSourceCode = nullptr; #include "CubeRendererDrawInstanced_GLSL_140.h" #include "CubeRendererDrawInstanced_HLSL_D3D10_D3D11.h" #include "CubeRendererDrawInstanced_Null.h" // Create the program mProgram = shaderLanguage->createProgram( shaderLanguage->createVertexShader(vertexShaderSourceCode), shaderLanguage->createFragmentShader(fragmentShaderSourceCode)); } // Is there a valid program? if (nullptr != mProgram) { // Create the vertex buffer object (VBO) static const float VERTEX_POSITION[] = { // Front face // Position TexCoord Normal // Vertex ID -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, // 0 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // 1 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // 2 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // 3 // Back face -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f,-1.0f, // 4 -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f,-1.0f, // 5 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,-1.0f, // 6 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f,-1.0f, // 7 // Top face -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 8 -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, // 9 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // 10 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 11 // Bottom face -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,-1.0f, 0.0f, // 12 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-1.0f, 0.0f, // 13 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f,-1.0f, 0.0f, // 14 -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,-1.0f, 0.0f, // 15 // Right face 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 16 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // 17 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, // 18 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 19 // Left face -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // 20 -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, // 21 -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, // 22 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f // 23 }; Renderer::IVertexBufferPtr vertexBuffer(mRenderer->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferUsage::STATIC_DRAW)); // Create the index buffer object (IBO) static const unsigned short INDICES[] = { // Front face Triangle ID 1, 0, 2, // 0 3, 2, 0, // 1 // Back face 6, 5, 4, // 2 4, 7, 6, // 3 // Top face 9, 8, 10, // 4 11, 10, 8, // 5 // Bottom face 13, 12, 14, // 6 15, 14, 12, // 7 // Right face 17, 16, 18, // 8 19, 18, 16, // 9 // Left face 21, 20, 22, // 10 23, 22, 20 // 11 }; Renderer::IIndexBuffer *indexBuffer = mRenderer->createIndexBuffer(sizeof(INDICES), Renderer::IndexBufferFormat::UNSIGNED_SHORT, INDICES, Renderer::BufferUsage::STATIC_DRAW); // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayAttribute vertexArray[] = { { // Attribute 0 // Data destination Renderer::VertexArrayFormat::FLOAT_3, // vertexArrayFormat (Renderer::VertexArrayFormat::Enum) "Position", // name[64] (char) "POSITION", // semantic[64] (char) 0, // semanticIndex (unsigned int) // Data source vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) 0, // offset (unsigned int) sizeof(float) * (3 + 2 + 3), // stride (unsigned int) // Data source, instancing part 0 // instancesPerElement (unsigned int) }, { // Attribute 1 // Data destination Renderer::VertexArrayFormat::FLOAT_2, // vertexArrayFormat (Renderer::VertexArrayFormat::Enum) "TexCoord", // name[64] (char) "TEXCOORD", // semantic[64] (char) 0, // semanticIndex (unsigned int) // Data source vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) sizeof(float) * 3, // offset (unsigned int) sizeof(float) * (3 + 2 + 3), // stride (unsigned int) // Data source, instancing part 0 // instancesPerElement (unsigned int) }, { // Attribute 2 // Data destination Renderer::VertexArrayFormat::FLOAT_3, // vertexArrayFormat (Renderer::VertexArrayFormat::Enum) "Normal", // name[64] (char) "NORMAL", // semantic[64] (char) 0, // semanticIndex (unsigned int) // Data source vertexBuffer, // pertexBuffer (Renderer::IVertexBuffer *) sizeof(float) * (3 + 2), // offset (unsigned int) sizeof(float) * (3 + 2 + 3), // stride (unsigned int) // Data source, instancing part 0 // instancesPerElement (unsigned int) } }; mVertexArray = mProgram->createVertexArray(sizeof(vertexArray) / sizeof(Renderer::VertexArrayAttribute), vertexArray, indexBuffer); } } // End debug event RENDERER_END_DEBUG_EVENT(&renderer) }
std::vector<AnimatedVertex> ModelBinaryLoader::readVertexBufferAnimation(int p_NumberOfVertex, std::istream* p_Input) { std::vector<AnimatedVertex> vertexBuffer(p_NumberOfVertex); p_Input->read(reinterpret_cast<char*>(vertexBuffer.data()), sizeof(AnimatedVertex) * p_NumberOfVertex); return vertexBuffer; }
void Font::read(const void * data, size_t size) { std::istringstream in(std::string(static_cast<const char*>(data), size)); // SignedDistanceFontFile sdff; // sdff.read(in); uint8_t header[4]; readStream(in, header); if (memcmp(header, "SDFF", 4)) { FAIL("Bad font file"); } uint16_t version; readStream(in, version); // read font name if (version > 0x0001) { char c; readStream(in, c); while (c) { mFamily += c; readStream(in, c); } } // read font data readStream(in, mLeading); readStream(in, mAscent); readStream(in, mDescent); readStream(in, mSpaceWidth); mFontSize = mAscent + mDescent; // read metrics data mMetrics.clear(); uint16_t count; readStream(in, count); for (int i = 0; i < count; ++i) { uint16_t charcode; readStream(in, charcode); Metrics & m = mMetrics[charcode]; readStream(in, m.ul.x); readStream(in, m.ul.y); readStream(in, m.size.x); readStream(in, m.size.y); readStream(in, m.offset.x); readStream(in, m.offset.y); readStream(in, m.d); m.lr = m.ul + m.size; } // read image data readPngToTexture((const char *) data + in.tellg(), size - in.tellg(), mTexture, mTextureSize); std::vector<TextureVertex> vertexData; std::vector<GLuint> indexData; float texH = 0, texW = 0, texA = 0; int characters = 0; std::for_each(mMetrics.begin(), mMetrics.end(), [&] ( MetricsData::reference & md ) { uint16_t id = md.first; Font::Metrics & m = md.second; ++characters; GLuint index = (GLuint)vertexData.size(); rectf bounds = getBounds(m, mFontSize); rectf texBounds = getTexCoords(m); QuadBuilder qb(bounds, texBounds); for (int i = 0; i < 4; ++i) { vertexData.push_back(qb.vertices[i]); } m.indexOffset = indexData.size(); indexData.push_back(index + 0); indexData.push_back(index + 1); indexData.push_back(index + 2); indexData.push_back(index + 0); indexData.push_back(index + 2); indexData.push_back(index + 3); }); gl::VertexBufferPtr vertexBuffer(new gl::VertexBuffer(vertexData)); gl::IndexBufferPtr indexBuffer(new gl::IndexBuffer(indexData)); mGeometry = gl::GeometryPtr( new gl::Geometry(vertexBuffer, indexBuffer, characters * 2, gl::Geometry::Flag::HAS_TEXTURE)); mGeometry->buildVertexArray(); }
//[-------------------------------------------------------] //[ Public virtual IApplication methods ] //[-------------------------------------------------------] void IcosahedronTessellation::onInitialization() { // Call the base implementation IApplicationRenderer::onInitialization(); // Get and check the renderer instance // -> Uniform buffer object (UBO, "constant buffer" in Direct3D terminology) supported? // -> Geometry shaders supported? // -> Tessellation control and tessellation evaluation shaders supported? Renderer::IRendererPtr renderer(getRenderer()); if (nullptr != renderer && renderer->getCapabilities().uniformBuffer && renderer->getCapabilities().maximumNumberOfGsOutputVertices > 0 && renderer->getCapabilities().maximumNumberOfPatchVertices > 0) { // Begin debug event RENDERER_BEGIN_DEBUG_EVENT_FUNCTION(renderer) // Decide which shader language should be used (for example "GLSL", "HLSL" or "Cg") Renderer::IShaderLanguagePtr shaderLanguage(renderer->getShaderLanguage()); if (nullptr != shaderLanguage) { // Create uniform buffers and fill the static buffers at once mUniformBufferDynamicTcs = shaderLanguage->createUniformBuffer(sizeof(float) * 2, nullptr, Renderer::BufferUsage::DYNAMIC_DRAW); { // "ObjectSpaceToClipSpaceMatrix" // TODO(co) Cleanup, correct aspect ratio glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3.0f)); glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f)); glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.001f, 1000.0f); glm::mat4 MVP = Projection * View; // glm::mat4 MVP = Projection * View * Model; mUniformBufferStaticTes = shaderLanguage->createUniformBuffer(sizeof(float) * 4 * 4, glm::value_ptr(MVP), Renderer::BufferUsage::STATIC_DRAW); { // "NormalMatrix" View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f)); Model = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f)); Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.001f, 1000.0f); MVP = Projection * View; glm::mat3 nMVP(MVP); glm::mat4 tMVP(nMVP); mUniformBufferStaticGs = shaderLanguage->createUniformBuffer(sizeof(float) * 4 * 4, glm::value_ptr(tMVP), Renderer::BufferUsage::STATIC_DRAW); } } { // Light and material static const float LIGHT_AND_MATERIAL[] = { 0.25f, 0.25f, 1.0f, 1.0, // "LightPosition" 0.0f, 0.75f, 0.75f,1.0, // "DiffuseMaterial" 0.04f, 0.04f, 0.04f,1.0, // "AmbientMaterial" }; mUniformBufferStaticFs = shaderLanguage->createUniformBuffer(sizeof(LIGHT_AND_MATERIAL), LIGHT_AND_MATERIAL, Renderer::BufferUsage::STATIC_DRAW); } { // Create the program // Get the shader source code (outsourced to keep an overview) const char *vertexShaderSourceCode = nullptr; const char *tessellationControlShaderSourceCode = nullptr; const char *tessellationEvaluationShaderSourceCode = nullptr; const char *geometryShaderSourceCode = nullptr; const char *fragmentShaderSourceCode = nullptr; #include "IcosahedronTessellation_GLSL_400.h" #include "IcosahedronTessellation_HLSL_D3D11.h" #include "IcosahedronTessellation_Null.h" // Create the program mProgram = shaderLanguage->createProgram( shaderLanguage->createVertexShader(vertexShaderSourceCode), shaderLanguage->createTessellationControlShader(tessellationControlShaderSourceCode), shaderLanguage->createTessellationEvaluationShader(tessellationEvaluationShaderSourceCode), shaderLanguage->createGeometryShader(geometryShaderSourceCode, Renderer::GsInputPrimitiveTopology::TRIANGLES, Renderer::GsOutputPrimitiveTopology::TRIANGLE_STRIP, 3), shaderLanguage->createFragmentShader(fragmentShaderSourceCode)); } // Is there a valid program? if (nullptr != mProgram) { // Create the vertex buffer object (VBO) // -> Geometry is from: http://prideout.net/blog/?p=48 (Philip Rideout, "The Little Grasshopper - Graphics Programming Tips") static const float VERTEX_POSITION[] = { // Vertex ID 0.000f, 0.000f, 1.000f, // 0 0.894f, 0.000f, 0.447f, // 1 0.276f, 0.851f, 0.447f, // 2 -0.724f, 0.526f, 0.447f, // 3 -0.724f, -0.526f, 0.447f, // 4 0.276f, -0.851f, 0.447f, // 5 0.724f, 0.526f, -0.447f, // 6 -0.276f, 0.851f, -0.447f, // 7 -0.894f, 0.000f, -0.447f, // 8 -0.276f, -0.851f, -0.447f, // 9 0.724f, -0.526f, -0.447f, // 10 0.000f, 0.000f, -1.000f // 11 }; Renderer::IVertexBufferPtr vertexBuffer(renderer->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferUsage::STATIC_DRAW)); // Create the index buffer object (IBO) // -> Geometry is from: http://prideout.net/blog/?p=48 (Philip Rideout, "The Little Grasshopper - Graphics Programming Tips") static const unsigned short INDICES[] = { // Triangle ID 2, 1, 0, // 0 3, 2, 0, // 1 4, 3, 0, // 2 5, 4, 0, // 3 1, 5, 0, // 4 11, 6, 7, // 5 11, 7, 8, // 6 11, 8, 9, // 7 11, 9, 10, // 8 11, 10, 6, // 9 1, 2, 6, // 10 2, 3, 7, // 11 3, 4, 8, // 12 4, 5, 9, // 13 5, 1, 10, // 14 2, 7, 6, // 15 3, 8, 7, // 16 4, 9, 8, // 17 5, 10, 9, // 18 1, 6, 10 // 19 }; Renderer::IIndexBuffer *indexBuffer = renderer->createIndexBuffer(sizeof(INDICES), Renderer::IndexBufferFormat::UNSIGNED_SHORT, INDICES, Renderer::BufferUsage::STATIC_DRAW); // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayAttribute vertexArray[] = { { // Attribute 0 // Data destination Renderer::VertexArrayFormat::FLOAT_3, // vertexArrayFormat (Renderer::VertexArrayFormat::Enum) "Position", // name[64] (char) "POSITION", // semantic[64] (char) 0, // semanticIndex (unsigned int) // Data source vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) 0, // offset (unsigned int) sizeof(float) * 3, // stride (unsigned int) // Data source, instancing part 0 // instancesPerElement (unsigned int) } }; mVertexArray = mProgram->createVertexArray(sizeof(vertexArray) / sizeof(Renderer::VertexArrayAttribute), vertexArray, indexBuffer); } } // End debug event RENDERER_END_DEBUG_EVENT(renderer) }