void Mesh::Initialize(const VertexAttributesMap_t& vertexAttributes) { vertexAttributes_ = vertexAttributes; // Calculate offset and array index depending on vertex attributes provided by the user map<size_t, VertexAttributes_t> attributesFromIndex; VertexAttributesMap_t::iterator it = vertexAttributes_.begin(); for (; it != vertexAttributes_.end(); ++it) { attributesFromIndex[it->second] = it->first; } bufferObjects_ = new BufferObject* [surfaces_.size()]; BufferUsage_t bufferUsage = (meshType_ == MESH_TYPE_STATIC) ? BUFFER_USAGE_STATIC : BUFFER_USAGE_DYNAMIC; for (size_t i = 0; i < surfaces_.size(); i++) { bufferObjects_[i] = Renderer::GetInstance()->GetBufferObjectManager()->CreateBufferObject(vertexAttributes_, bufferUsage); BufferObject* bufferObject = bufferObjects_[i]; vector<float> data; int presentVertexAttributes; size_t stride; PackSurfaceTriangleVertices(surfaces_[i], attributesFromIndex, data, presentVertexAttributes, stride); if (bufferObject->SetVertexData(data, presentVertexAttributes) != BUFFER_OBJECT_ERROR_NONE) { Logger::GetInstance()->Error("The vertex attributes are not all present"); FreeMeshMemory(); break; } bufferObject->SetIndexData(surfaces_[i]->indices, surfaces_[i]->numIndices); } ConstructBoundingSphere(); }
void init(Renderer &gfx, Context &ctx) { // Use the compute shader to work magic on the texture gfx.beginCustomShader(shader_compute); gfx.setUniform("inTex", 0); gfx.setUniform("outTex", 1); glBindImageTexture(0, tex.getHandle(), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA16F); glBindImageTexture(1, tex_blurred.getHandle(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); glDispatchCompute( tex.getWidth() / NUM_GROUPS_X, tex.getHeight() / NUM_GROUPS_Y, 1); const float vertices[] = { -1.0f, -1.0f, +1.0f, -1.0f, +1.0f, +1.0f, +1.0f, +1.0f, -1.0f, +1.0f, -1.0f, -1.0f }; vbo.create(GL_ARRAY_BUFFER, GL_STATIC_DRAW); vbo.bind(); vbo.bufferData(sizeof(vertices), vertices); vao.create(); vao.bind(); }
/*------------------------------------- * Copy data from one buffer into another. -------------------------------------*/ bool BufferObject::copy_data(const BufferObject& from) noexcept { LS_DEBUG_ASSERT(from.gpuId != this->gpuId); LS_DEBUG_ASSERT(this->is_valid()); LS_DEBUG_ASSERT(from.is_valid()); LS_DEBUG_ASSERT(from.get_type() == this->get_type()); // bind the buffers to OGL's read/write targets to prevent a pipeline stall. glBindBuffer(VBO_COPY_READ, from.gpuId); GLint numBytes = 0; buffer_access_t usage = buffer_access_t::VBO_STATIC_DRAW; glGetBufferParameteriv(VBO_COPY_READ, GL_BUFFER_SIZE, &numBytes); glGetBufferParameteriv(VBO_COPY_READ, GL_BUFFER_USAGE, (GLint*) & usage); if (numBytes != 0 && !this->gpuId) { if (!init()) { terminate(); return false; } } glBindBuffer(VBO_COPY_WRITE, this->gpuId); glBufferData(VBO_COPY_WRITE, numBytes, nullptr, usage); glCopyBufferSubData(VBO_COPY_READ, VBO_COPY_WRITE, 0, 0, numBytes); // better safe than sorry glBindBuffer(VBO_COPY_READ, 0); glBindBuffer(VBO_COPY_WRITE, 0); copy_attribs(from); return true; }
BufferGL4<Tag>::BufferGL4(void const* sourceData, std::size_t sizeInBytes, BufferUsage bufferUsage) { POMDOG_ASSERT(bufferUsage == BufferUsage::Immutable ? sourceData != nullptr : true); // Generate new buffer bufferObject = ([] { BufferObject buffer; glGenBuffers(1, buffer.Data()); return std::move(buffer); })(); POMDOG_CHECK_ERROR_GL4("glGenBuffers"); auto const oldBuffer = TypesafeHelperGL4::Get<BufferObject>(); ScopeGuard scope([&] { TypesafeHelperGL4::BindBuffer(oldBuffer); }); POMDOG_ASSERT(bufferObject); TypesafeHelperGL4::BindBuffer(*bufferObject); POMDOG_CHECK_ERROR_GL4("glBindBuffer"); POMDOG_ASSERT(sizeInBytes > 0); glBufferData(BufferTraits<Tag>::Buffer, sizeInBytes, sourceData, ToBufferUsage(bufferUsage)); POMDOG_CHECK_ERROR_GL4("glBufferData"); }
void BufferObject::copy(const BufferObject& source, uint32_t sourceOffset, uint32_t targetOffset, uint32_t size) { source.bind(TARGET_COPY_READ_BUFFER); bind(TARGET_COPY_WRITE_BUFFER); glCopyBufferSubData(TARGET_COPY_READ_BUFFER, TARGET_COPY_WRITE_BUFFER, sourceOffset, targetOffset, size); unbind(TARGET_COPY_WRITE_BUFFER); source.unbind(TARGET_COPY_READ_BUFFER); GET_GL_ERROR(); }
void VertexBuffer::drawIndexed(BufferObject &ibo, Shader &shader, GLenum mode, int count) { bind(); ibo.bind(); mapAttributes(shader); enableVertexAttributes(); glf->glDrawElements(mode, count ? count : ibo.size()/sizeof(uint32), GL_UNSIGNED_INT, nullptr); disableVertexAttributes(); ibo.unbind(); unbind(); }
void GlContext::copy_buffer_data(const BufferObject& from, BufferObject& to, size_t offset_from, size_t offset_to, size_t count) { glBindBuffer(GL_COPY_READ_BUFFER, from.handle()); CHECK_GL_ERROR(glBindBuffer); glBindBuffer(GL_COPY_WRITE_BUFFER, to.handle()); CHECK_GL_ERROR(glBindBuffer); glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, offset_from, offset_to, count); rebind_buffer_object(); CHECK_GL_ERROR(glCopyBufferSubData); }
void VertexArrayObject::BindBuffer(int location, BufferObject &buffer, int size, DataType type, bool normalized, int stride, int offset) { GL_CHECKED(glEnableVertexAttribArray(location)); buffer.Begin(); if (IsIntegerDataType(type)) { GL_CHECKED(glVertexAttribIPointer(location, size, GetDataType(type), stride, (GLvoid *)offset)); } else { GL_CHECKED(glVertexAttribPointer(location, size, GetDataType(type), normalized ? GL_TRUE : GL_FALSE, stride, (GLvoid *)offset)); } buffer.End(); }
void Texture::copyPbo(BufferObject &pbo, int level) { pbo.bind(); switch (_type) { case TEXTURE_BUFFER: FAIL("PBO copy not available for texture buffer - use BufferObject::copyData instead"); break; default: copy(nullptr, level); } pbo.unbind(); }
Sphere::Sphere(int slices, int stacks) { std::vector<GLfloat> vertices; for (int j = 0; j <= stacks; j++) { for (int i = 0; i <= slices; i++) { float theta = static_cast<float>((i / (float) slices) * 2 * M_PI); float phi = static_cast<float>((j / (float)stacks) * M_PI); vertices.push_back(cos(theta) * sin(phi)); vertices.push_back(cos(phi)); vertices.push_back(sin(theta) * sin(phi)); } } std::vector<GLfloat> normals = vertices; std::vector<GLuint> indices; for (int j = 0; j < slices; j++) { for (int i = 0; i < stacks; i++) { indices.push_back(i + j * (slices + 1)); indices.push_back((i + 1) + (j + 1) * (slices + 1)); indices.push_back(i + (j + 1) * (slices + 1)); indices.push_back(i + j * (slices + 1)); indices.push_back((i + 1) + j * (slices + 1)); indices.push_back((i + 1) + (j + 1) * (slices + 1)); } } BufferObject* vbuff = new BufferObject(GL_ARRAY_BUFFER, sizeof(GLfloat)* vertices.size(), GL_STATIC_DRAW); vbuff->sendData(&vertices[0]); attachBuffer(vbuff); BufferObject* nbuff = new BufferObject(GL_ARRAY_BUFFER, sizeof(GLfloat)* normals.size(), GL_STATIC_DRAW); nbuff->sendData(&normals[0]); attachBuffer(nbuff); bind(); BufferObject* ibuff = new BufferObject(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)* indices.size(), GL_STATIC_DRAW); ibuff->sendData(&indices[0]); attachBuffer(ibuff); vbuff->bind(); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(0); nbuff->bind(); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(1); glBindVertexArray(0); m_numPoints = indices.size(); vertices.clear(); indices.clear(); normals.clear(); }
/*------------------------------------- * Copy attribs from the input parameter into *this. -------------------------------------*/ bool VertexBuffer::copy_attribs(const BufferObject& from) noexcept { LS_DEBUG_ASSERT(from.get_type() == buffer_use_t::VBO_BUFFER_ARRAY); const VertexBuffer * const pVbo = static_cast<const VertexBuffer*>(&from); attribs = pVbo->attribs; return BufferObject::copy_attribs<VertexBuffer, VBOAttrib>(*pVbo, *this); }
// lyc modification BufferObject * MemoryManager:: findBufferByAddr(uint64_t addr){ BufferObject * bf = NULL; for(std::set<MemoryObject*> :: iterator it = objects.begin(); it != objects.end(); it++){ uint64_t addr_start = (*it)->address; ref<ConstantExpr> sizeExpr = (*it)->getSizeExpr(); uint64_t size = sizeExpr->getZExtValue(); uint64_t addr_end = addr_start + size - 1; if(addr <= addr_end && addr >= addr_start) { bf = new BufferObject(*it); bf->setStartAddr(addr); bf->setSize(addr_end - addr + 1); // printf("Debug: findBufferByAddr: start address: %u, end address: %u, size: %u\n", (unsigned)addr, // (unsigned)addr_end, (unsigned)size); return bf; } } return NULL; }
BoundBufferObject GlContext::bind_buffer_object(BufferObject& buffer) { if(m_bound_buffer_object != nullptr) { throw TargetBindError(Target::Buffer); } glBindBuffer(GL_COPY_WRITE_BUFFER, buffer.handle()); CHECK_GL_ERROR(glBindBuffer); return BoundBufferObject(&buffer, this, TargetLock(&buffer, &m_bound_buffer_object)); }
void render(Renderer &gfx, Context &ctx, double dt) { gfx.setClearDepth(1.0); gfx.setClearColor(0.2f, 0.2f, 0.3f); gfx.clearColorAndDepth(); gfx.setDepthTestState(DepthTestStates::LessThanOrEqual); gfx.setCullState(CullStates::CullNone); gfx.beginCustomShader(shader); gfx.setUniform("view", mat4(1.0f)); gfx.setUniform("projection", glm::perspective(45.0f, ctx.getWidth() / (float)ctx.getHeight(), 0.05f, 10.0f)); gfx.setUniform("model", transform::translate(0.0f, 0.0f, -3.5f) * transform::rotateY(ctx.getElapsedTime())); vao.bind(); vbo.bind(); // This is necessary // These aren't! //gfx.setAttributefv("position", 3, 7, 0); //gfx.setAttributefv("color", 4, 7, 3); // Update buffer with dynamic data float sint = sin(ctx.getElapsedTime()); float cost = cos(ctx.getElapsedTime()); float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f * sint + 0.5f, 0.5f * cost + 0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.0f, 0.5f * sint + 0.5f, 0.5f * cost + 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.0f, 0.5f * sint + 0.5f, 0.5f * cost + 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.0f, 0.5f * sint + 0.5f, 0.5f * cost + 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.0f, 0.5f * sint + 0.5f, 0.5f * cost + 0.5f, 1.0f, 1.0f, -0.5f, -0.5f, 0.0f, 0.5f * sint + 0.5f, 0.5f * cost + 0.5f, 1.0f, 1.0f }; vbo.bufferSubData(0, sizeof(vertices), vertices); glDrawArrays(GL_TRIANGLES, 0, 6); gfx.endCustomShader(); }
void init(Renderer &gfx, Context &ctx) { // Create the vertex buffer that will be updated with vertices during runtime vbo.create(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW); vbo.bind(); vbo.bufferData(sizeof(float) * 6 * 7, NULL); vbo.unbind(); // Create VAO to hold attribute bindings vao.create(); vao.bind(); vbo.bind(); shader.setAttributefv("position", 3, 7, 0); shader.setAttributefv("color", 4, 7, 3); vbo.unbind(); vao.unbind(); }
void setupLights() { //Sphere** lightMesh = new Sphere*[NUM_LIGHTS]; Light** lightSources = new Light*[NUM_LIGHTS]; for (int i = 0; i < NUM_LIGHTS; i++) { lightSources[i] = new Light(); lightSources[i]->setPosition(glm::vec3(rand() % 50, 5 + rand() % 10, rand() % 50)); lightSources[i]->setColor(glm::vec3((float)rand() / (float)RAND_MAX, (float)rand() / (float)RAND_MAX, (float)rand() / (float)RAND_MAX)); TinyGL::getInstance()->addResource(LIGHT, "light" + to_string(i), lightSources[i]); /*lightMesh[i] = new Sphere(20, 20); lightMesh[i]->setDrawCb(drawSphere); lightMesh[i]->setMaterialColor(glm::vec4(lightSources[i]->getColor(), 1.f)); lightMesh[i]->m_modelMatrix = glm::translate(glm::vec3(lightSources[i]->getPosition())) * glm::scale(glm::vec3(0.1f)); TinyGL::getInstance()->addResource(MESH, "lightMesh" + to_string(i), lightMesh[i]);*/ } GLfloat* lightCoords = new GLfloat[4 * NUM_LIGHTS]; for (int i = 0; i < NUM_LIGHTS; i++) { glm::vec3 pos = lightSources[i]->getPosition(); lightCoords[i * 4] = pos.x; lightCoords[i * 4 + 1] = pos.y; lightCoords[i * 4 + 2] = pos.z; lightCoords[i * 4 + 3] = 1.f; } for (int i = 0; i < NUM_LIGHTS; i++) cout << "(" << lightCoords[i * 4] << ", " << lightCoords[i * 4 + 1] << ", " << lightCoords[i * 4 + 2] << ", " << lightCoords[i * 4 + 3] << ")\n"; /*GLfloat* lightColors = new GLfloat[4 * NUM_LIGHTS]; for (int i = 0; i < NUM_LIGHTS; i++) { glm::vec3 color = lightSources[i]->getColor(); lightColors[i * 4] = color.x; lightColors[i * 4 + 1] = color.y; lightColors[i * 4 + 2] = color.z; lightColors[i * 4 + 3] = 1.f; }*/ Shader* s = TinyGL::getInstance()->getShader("sPass"); s->setUniform1i("u_numLights", NUM_LIGHTS); GLuint idxPos = glGetUniformBlockIndex(s->getProgramId(), "LightPos"); glUniformBlockBinding(s->getProgramId(), idxPos, 0); /*GLuint idxColor = glGetUniformBlockIndex(s->getProgramId(), "LightColor"); glUniformBlockBinding(s->getProgramId(), idxColor, 1);*/ BufferObject* ubuffLightPos = new BufferObject(GL_UNIFORM_BUFFER, sizeof(GLfloat)* 3 * NUM_LIGHTS, GL_STATIC_DRAW); ubuffLightPos->sendData(lightCoords); /*BufferObject* ubuffLightColor = new BufferObject(GL_UNIFORM_BUFFER, sizeof(GLfloat)* 3 * NUM_LIGHTS, GL_STATIC_DRAW); ubuffLightColor->sendData(lightColors);*/ glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubuffLightPos->getId()); //glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubuffLightColor->getId()); TinyGL::getInstance()->addResource(BUFFER, "lightpos_buff", ubuffLightPos); //TinyGL::getInstance()->addResource(BUFFER, "lightcolor_buff", ubuffLightColor); delete lightCoords; //delete lightColors; }
BufferObject::Binder::Binder( const BufferObject& bo ) : m_bo( bo ) { KVS_ASSERT( bo.isCreated() ); bo.bind(); }
Grid::Grid(int nx, int ny) : Mesh() { std::vector<GLfloat> vertices; float h_step = static_cast<float>(1.f / nx); float v_step = static_cast<float>(1.f / ny); for (int i = 0; i < nx; i++) { for (int j = 0; j < ny; j++) { vertices.push_back(static_cast<float>(i * h_step)); vertices.push_back(static_cast<float>(j * v_step)); vertices.push_back(0.f); } } std::vector<GLuint> indices; for (int i = 0; i < nx - 1; i++) { for (int j = 0; j < ny - 1; j++) { indices.push_back(i * nx + j); indices.push_back((i + 1) * nx + j); indices.push_back(i * nx + (j + 1)); indices.push_back((i + 1) * nx + j); indices.push_back((i + 1) * nx + (j + 1)); indices.push_back(i * nx + (j + 1)); } } std::vector<GLfloat> normals; for (size_t i = 0; i < vertices.size(); i += 3) { normals.push_back(0); normals.push_back(0); normals.push_back(-1); } BufferObject* vbuff = new BufferObject(GL_ARRAY_BUFFER, sizeof(GLfloat)* vertices.size(), GL_STATIC_DRAW); vbuff->sendData(&vertices[0]); attachBuffer(vbuff); BufferObject* nbuff = new BufferObject(GL_ARRAY_BUFFER, sizeof(GLfloat)* normals.size(), GL_STATIC_DRAW); nbuff->sendData(&normals[0]); attachBuffer(nbuff); bind(); BufferObject* ibuff = new BufferObject(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), GL_STATIC_DRAW); ibuff->sendData(&indices[0]); attachBuffer(ibuff); vbuff->bind(); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(0); nbuff->bind(); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(1); glBindVertexArray(0); m_numPoints = indices.size(); vertices.clear(); indices.clear(); normals.clear(); }
void MESHsetup() { #ifdef _DEBUG std::cout << "Setup meshes" << std::endl; #endif VertexFormat *fmt; { VertexFormat tmp; tmp.addAttribute(VertexAttribute(VAS_POSITION, VAT_FLOAT, 3)); tmp.addAttribute(VertexAttribute(VAS_NORMAL, VAT_FLOAT, 3)); tmp.addAttribute(VertexAttribute(VAS_TEXCOORD, VAT_FLOAT, 2)); cout << tmp.toString() << endl; cout << "Size in bytes: " << (unsigned long)(tmp.getBytesSize()) << endl; fmt = VertexFormat::Register(tmp); } //BufferObject::Usage usage = //BufferObject::Usage(BufferObject::BOU_STATIC|BufferObject::BOU_DRAW); BufferObject *vbo = NULL; CubeMesh = new SubMesh(); //if (CubeMesh->createIndexed(usage, fmt, 24, 36)) { //nvert, nindex if (CubeMesh->createIndexed(SubMesh::PT_TRI, fmt, 24, SubMesh::IT_8, 36)) { //nvert, nindex vbo = CubeMesh->getVertexBuffer(); vbo->bind(); //vbo->upload(0, sizeof(CubeVertexData), CubeVertexData); vbo->upload(sizeof(CubeVertexData), CubeVertexData, BufferObject::BOU_STATIC); vbo = CubeMesh->getIndexBuffer(); vbo->bind(); //vbo->upload(0, sizeof(CubeFaceData), CubeFaceData); vbo->upload(sizeof(CubeFaceData), CubeFaceData, BufferObject::BOU_STATIC); } PlaneMesh = new SubMesh(); //if (PlaneMesh->createIndexed(usage, fmt, 4, 6)) { // nvert, nindex if (PlaneMesh->createIndexed(SubMesh::PT_TRI, fmt, 4, SubMesh::IT_8, 6)) { // nvert, nindex vbo = PlaneMesh->getVertexBuffer(); vbo->bind(); //vbo->upload(0, sizeof(PlaneVertexData), PlaneVertexData); vbo->upload(sizeof(PlaneVertexData), PlaneVertexData, BufferObject::BOU_STATIC); vbo = PlaneMesh->getIndexBuffer(); vbo->bind(); //vbo->upload(0, sizeof(PlaneFaceData), PlaneFaceData); vbo->upload(sizeof(PlaneFaceData), PlaneFaceData, BufferObject::BOU_STATIC); } /* std::string fmtStr = "P-3-N-3-T0-2"; VertexFormat *fmt = VertexFormat::Get(fmtStr); BufferObject::Usage usage = BufferObject::Usage(BufferObject::BOU_STATIC|BufferObject::BOU_DRAW); BufferObject *vbo = NULL; CubeMesh = new SubMesh(); if (CubeMesh->createIndexed(usage, fmt, 24, 36)) { //nvert, nindex vbo = CubeMesh->vertexBuffer(); vbo->bind(); vbo->upload(0, sizeof(CubeVertexData), CubeVertexData); vbo = CubeMesh->indexBuffer(); vbo->bind(); vbo->upload(0, sizeof(CubeFaceData), CubeFaceData); } PlaneMesh = new SubMesh(); if (PlaneMesh->createIndexed(usage, fmt, 4, 6)) { // nvert, nindex vbo = PlaneMesh->vertexBuffer(); vbo->bind(); vbo->upload(0, sizeof(PlaneVertexData), PlaneVertexData); vbo = PlaneMesh->indexBuffer(); vbo->bind(); vbo->upload(0, sizeof(PlaneFaceData), PlaneFaceData); } */ }
void apply(CoreRenderingStatus & target, const CoreRenderingStatus & actual, bool forced) { // Blending if(forced || target.blendingParametersChanged(actual)) { const BlendingParameters & targetParams = target.getBlendingParameters(); const BlendingParameters & actualParams = actual.getBlendingParameters(); if(forced || targetParams.isEnabled() != actualParams.isEnabled()) { if(actualParams.isEnabled()) { glEnable(GL_BLEND); } else { glDisable(GL_BLEND); } } if(forced || targetParams.getBlendFuncSrcRGB() != actualParams.getBlendFuncSrcRGB() || targetParams.getBlendFuncDstRGB() != actualParams.getBlendFuncDstRGB() || targetParams.getBlendFuncSrcAlpha() != actualParams.getBlendFuncSrcAlpha() || targetParams.getBlendFuncDstAlpha() != actualParams.getBlendFuncDstAlpha()) { glBlendFuncSeparate(BlendingParameters::functionToGL(actualParams.getBlendFuncSrcRGB()), BlendingParameters::functionToGL(actualParams.getBlendFuncDstRGB()), BlendingParameters::functionToGL(actualParams.getBlendFuncSrcAlpha()), BlendingParameters::functionToGL(actualParams.getBlendFuncDstAlpha())); } if(forced || targetParams.getBlendColor() != actualParams.getBlendColor()) { glBlendColor(actualParams.getBlendColor().getR(), actualParams.getBlendColor().getG(), actualParams.getBlendColor().getB(), actualParams.getBlendColor().getA()); } if(forced || targetParams.getBlendEquationRGB() != actualParams.getBlendEquationRGB() || targetParams.getBlendEquationAlpha() != actualParams.getBlendEquationAlpha()) { glBlendEquationSeparate(BlendingParameters::equationToGL(actualParams.getBlendEquationRGB()), BlendingParameters::equationToGL(actualParams.getBlendEquationAlpha())); } target.updateBlendingParameters(actual); } // ColorBuffer if(forced || target.colorBufferParametersChanged(actual)) { glColorMask( actual.getColorBufferParameters().isRedWritingEnabled() ? GL_TRUE : GL_FALSE, actual.getColorBufferParameters().isGreenWritingEnabled() ? GL_TRUE : GL_FALSE, actual.getColorBufferParameters().isBlueWritingEnabled() ? GL_TRUE : GL_FALSE, actual.getColorBufferParameters().isAlphaWritingEnabled() ? GL_TRUE : GL_FALSE ); target.setColorBufferParameters(actual.getColorBufferParameters()); } GET_GL_ERROR(); // CullFace if(forced || target.cullFaceParametersChanged(actual)) { if(actual.getCullFaceParameters().isEnabled()) { glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } switch(actual.getCullFaceParameters().getMode()) { case CullFaceParameters::CULL_BACK: glCullFace(GL_BACK); break; case CullFaceParameters::CULL_FRONT: glCullFace(GL_FRONT); break; case CullFaceParameters::CULL_FRONT_AND_BACK: glCullFace(GL_FRONT_AND_BACK); break; default: throw std::invalid_argument("Invalid CullFaceParameters::cullFaceMode_t enumerator"); } target.setCullFaceParameters(actual.getCullFaceParameters()); } // DepthBuffer if(forced || target.depthBufferParametersChanged(actual)) { if(actual.getDepthBufferParameters().isTestEnabled()) { glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } if(actual.getDepthBufferParameters().isWritingEnabled()) { glDepthMask(GL_TRUE); } else { glDepthMask(GL_FALSE); } glDepthFunc(Comparison::functionToGL(actual.getDepthBufferParameters().getFunction())); target.setDepthBufferParameters(actual.getDepthBufferParameters()); } GET_GL_ERROR(); // Line if(forced || target.lineParametersChanged(actual)) { auto width = actual.getLineParameters().getWidth(); glLineWidth(RenderingContext::getCompabilityMode() ? width : std::min(width, 1.0f)); target.setLineParameters(actual.getLineParameters()); } // stencil if (forced || target.stencilParametersChanged(actual)) { const StencilParameters & targetParams = target.getStencilParameters(); const StencilParameters & actualParams = actual.getStencilParameters(); if(forced || targetParams.isEnabled() != actualParams.isEnabled()) { if(actualParams.isEnabled()) { glEnable(GL_STENCIL_TEST); } else { glDisable(GL_STENCIL_TEST); } } if(forced || targetParams.differentFunctionParameters(actualParams)) { glStencilFunc(Comparison::functionToGL(actualParams.getFunction()), actualParams.getReferenceValue(), actualParams.getBitMask().to_ulong()); } if(forced || targetParams.differentActionParameters(actualParams)) { glStencilOp(convertStencilAction(actualParams.getFailAction()), convertStencilAction(actualParams.getDepthTestFailAction()), convertStencilAction(actualParams.getDepthTestPassAction())); } target.updateStencilParameters(actual); } GET_GL_ERROR(); #ifdef LIB_GL if(RenderingContext::getCompabilityMode()) { // AlphaTest if(forced || target.alphaTestParametersChanged(actual)) { if(actual.getAlphaTestParameters().isEnabled()) { glDisable(GL_ALPHA_TEST); } else { glEnable(GL_ALPHA_TEST); } glAlphaFunc(Comparison::functionToGL(actual.getAlphaTestParameters().getMode()), actual.getAlphaTestParameters().getReferenceValue()); target.setAlphaTestParameters(actual.getAlphaTestParameters()); } GET_GL_ERROR(); } #endif /* LIB_GL */ // Lighting if(forced || target.lightingParametersChanged(actual)) { #ifdef LIB_GL if(RenderingContext::getCompabilityMode()) { if(actual.getLightingParameters().isEnabled()) { glEnable(GL_LIGHTING); } else { glDisable(GL_LIGHTING); } } #endif /* LIB_GL */ target.setLightingParameters(actual.getLightingParameters()); } GET_GL_ERROR(); #ifdef LIB_GL // polygonMode if(forced || target.polygonModeParametersChanged(actual) ) { glPolygonMode(GL_FRONT_AND_BACK, PolygonModeParameters::modeToGL(actual.getPolygonModeParameters().getMode())); target.setPolygonModeParameters(actual.getPolygonModeParameters()); } GET_GL_ERROR(); #endif /* LIB_GL */ // PolygonOffset if(forced || target.polygonOffsetParametersChanged(actual)) { if(actual.getPolygonOffsetParameters().isEnabled()) { glEnable(GL_POLYGON_OFFSET_FILL); #ifdef LIB_GL glEnable(GL_POLYGON_OFFSET_LINE); glEnable(GL_POLYGON_OFFSET_POINT); #endif /* LIB_GL */ glPolygonOffset(actual.getPolygonOffsetParameters().getFactor(), actual.getPolygonOffsetParameters().getUnits()); } else { glDisable(GL_POLYGON_OFFSET_FILL); #ifdef LIB_GL glDisable(GL_POLYGON_OFFSET_LINE); glDisable(GL_POLYGON_OFFSET_POINT); #endif /* LIB_GL */ } target.setPolygonOffsetParameters(actual.getPolygonOffsetParameters()); } GET_GL_ERROR(); // PrimitiveRestart #ifdef LIB_GL if(forced || target.primitiveRestartParametersChanged(actual)) { if(actual.getPrimitiveRestartParameters().isEnabled()) { glEnable(GL_PRIMITIVE_RESTART); glPrimitiveRestartIndex(actual.getPrimitiveRestartParameters().getIndex()); } else { glDisable(GL_PRIMITIVE_RESTART); } target.setPrimitiveRestartParameters(actual.getPrimitiveRestartParameters()); } GET_GL_ERROR(); #endif /* LIB_GL */ // Textures if(forced || target.texturesChanged(actual)) { for(uint_fast8_t unit = 0; unit < MAX_TEXTURES; ++unit) { const auto & texture = actual.getTexture(unit); const auto & oldTexture = target.getTexture(unit); if(forced || texture != oldTexture) { glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(unit)); if( texture ) { glBindTexture(texture->getGLTextureType(), texture->getGLId()); #if defined(LIB_GL) BufferObject* buffer = texture->getBufferObject(); if(buffer) glTexBuffer( GL_TEXTURE_BUFFER, texture->getFormat().pixelFormat.glInternalFormat, buffer->getGLId() ); #endif } else if( oldTexture ) { glBindTexture(oldTexture->getGLTextureType(), 0); } else { glBindTexture(GL_TEXTURE_2D, 0); } } } target.updateTextures(actual); } GET_GL_ERROR(); }
void free() { vao.dispose(); vbo.dispose(); }
void run() { if(!initialize()) shutdown("Failed to initialize"); if(!loadContent()) shutdown("Failed to load resources"); Mesh cubeMesh = Mesh::genUnitColoredCube(); MeshBuffer cubeBuffer(cubeMesh); Model cube(cubeBuffer); Mesh waterMesh = Mesh::genUnitColoredPlane(Color(0.57f, 0.63f, 0.98f)); MeshBuffer waterBuffer(waterMesh); Model water(waterBuffer); BufferObject quadVbo; float quadVertices[] = { -1.0f, -1.0f, 0.0f, 0.0f, +1.0f, -1.0f, 1.0f, 0.0f, +1.0f, +1.0f, 1.0f, 1.0f, +1.0f, +1.0f, 1.0f, 1.0f, -1.0f, +1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f }; quadVbo.create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, sizeof(quadVertices), quadVertices); Mesh gridMesh; for(int i = 0; i <= 8; ++i) { float f = (i / 8.0) * 2.0f - 1.0f; int j = gridMesh.getPositionCount(); gridMesh.addPosition(f * 3.0f, 0.0f, -3.0f); gridMesh.addPosition(f * 3.0f, 0.0f, +3.0f); gridMesh.addPosition(-3.0f, 0.0f, f * 3.0f); gridMesh.addPosition(+3.0f, 0.0f, f * 3.0f); gridMesh.addColor(Colors::White); gridMesh.addColor(Colors::White); gridMesh.addColor(Colors::White); gridMesh.addColor(Colors::White); gridMesh.addIndex(j + 0); gridMesh.addIndex(j + 1); gridMesh.addIndex(j + 2); gridMesh.addIndex(j + 3); } MeshBuffer gridBuffer(gridMesh); Model grid(gridBuffer); VertexArray vao; vao.create(); vao.bind(); mat4 perspectiveMatrix = glm::perspective(45.0f, windowWidth / float(windowHeight), 0.05f, 50.0f); // The geometry to be refracted and reflected are stored in these // In addition to RGB values, the world-space height is stored in the alpha-channel // of the refraction texture. // Fresnel equations is used to blend between the two textures RenderTexture refractionRT(windowWidth, windowHeight); RenderTexture reflectionRT(windowWidth, windowHeight); renderer.setClearColor(0.55f, 0.45f, 0.45f, 1.0f); renderer.setClearDepth(1.0); Timer timer; timer.start(); double renderTime = 0.0; while(context.isOpen()) { timer.step(); double time = timer.getElapsedTime(); update(time, timer.getDelta()); double renderStart = timer.getElapsedTime(); MatrixStack viewMatrix; viewMatrix.push(); viewMatrix.translate(0.0f, 0.0f, -3.0f); viewMatrix.rotateX(xAxisRotation); viewMatrix.rotateY(yAxisRotation); renderer.setCullState(CullStates::CullNone); renderer.setDepthTestState(DepthTestStates::LessThanOrEqual); colorShader.begin(); colorShader.setUniform("projection", perspectiveMatrix); cube.pushTransform(); cube.translate(0.0f, 0.0f, 0.0f); cube.scale(0.5f); // Render the geometry to be refracted, store result in rt refractionRT.begin(); renderer.clearColorAndDepth(); colorShader.setUniform("view", viewMatrix.top()); cube.draw(GL_TRIANGLES); grid.draw(GL_LINES); refractionRT.end(); // Render the geometry to be reflected, store result in rt reflectionRT.begin(); renderer.clearColorAndDepth(); viewMatrix.push(); viewMatrix.scale(1.0f, -1.0f, 1.0f); // Reflect about xz-plane colorShader.setUniform("view", viewMatrix.top()); cube.draw(GL_TRIANGLES); viewMatrix.pop(); reflectionRT.end(); colorShader.end(); cube.popTransform(); // Render the water with the previous reflection/refraction texture waterShader.begin(); waterShader.setUniform("time", time); glActiveTexture(GL_TEXTURE0 + 0); refractionRT.bindTexture(); glActiveTexture(GL_TEXTURE0 + 1); reflectionRT.bindTexture(); glActiveTexture(GL_TEXTURE0 + 2); waterNormals.bind(); //waterShader.setUniform("view", viewMatrix.top()); waterShader.setUniform("refraction_tex", 0); waterShader.setUniform("reflection_tex", 1); waterShader.setUniform("water_normals_tex", 2); //waterShader.setUniform("light0_pos", vec3(0.0f, 1.0f, 0.0f)); //waterShader.setUniform("light0_col", vec3(1.0f, 0.8f, 0.5f)); //waterShader.setUniform("ambient", vec3(67.0f/255.0f, 66.0f/255.0f, 63.0f/255.0f)); quadVbo.bind(); waterShader.setAttributefv("position", 2, 4, 0); waterShader.setAttributefv("texel", 2, 4, 2); glDrawArrays(GL_TRIANGLES, 0, 6); quadVbo.unbind(); reflectionRT.unbindTexture(); refractionRT.unbindTexture(); waterNormals.unbind(); waterShader.end(); glActiveTexture(GL_TEXTURE0 + 0); // Render unmirrored scene //colorShader.begin(); //renderer.clearColorAndDepth(); //renderer.setCullState(CullStates::CullNone); //renderer.setBlendState(BlendStates::AlphaBlend); //renderer.setDepthTestState(DepthTestStates::LessThanOrEqual); //colorShader.setUniform("projection", perspectiveMatrix); //colorShader.setUniform("view", viewMatrix.top()); //cube.pushTransform(); //cube.translate(0.0f, 0.4f, 0.0f); //cube.scale(0.5f); //cube.draw(GL_TRIANGLES); /*grid.pushTransform(); grid.translate(0.0f, -0.5f, 0.0f); grid.draw(GL_LINES); grid.popTransform();*/ // Draw mirrored scene to a rendertarget /*rt.begin(); renderer.clearColorAndDepth(); viewMatrix.push(); viewMatrix.scale(1.0f, -1.0f, 1.0f); colorShader.setUniform("view", viewMatrix.top()); cube.draw(GL_TRIANGLES); cube.popTransform(); viewMatrix.pop(); rt.end();*/ // Enable stencil testing and mask out a section containing the water mesh //glEnable(GL_STENCIL_TEST); //glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to 1 //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); //glStencilMask(0xFF); // Write to stencil buffer //glDepthMask(GL_FALSE); // Don't write to depth buffer //glClear(GL_STENCIL_BUFFER_BIT); // Clear stencil buffer (0 by default) //// Draw water mesh //water.pushTransform(); //water.scale(3.0f); //water.draw(GL_TRIANGLES); //water.popTransform(); //colorShader.end(); //// Draw previous rendertarget as a quad masked into the water plane //glStencilFunc(GL_EQUAL, 1, 0xFF); // Pass test if stencil value is 1 //glStencilMask(0x00); // Don't write anything to stencil buffer //glDepthMask(GL_TRUE); //glDisable(GL_STENCIL_TEST); viewMatrix.pop(); context.display(); renderTime = timer.getElapsedTime() - renderStart; if(renderTime < 0.013) context.sleep(0.013 - renderTime); if(checkGLErrors(std::cerr)) { std::cin.get(); context.close(); } } waterNormals.dispose(); colorShader.dispose(); waterShader.dispose(); vao.dispose(); context.dispose(); }
void SkinnedMesh::Initialize(const VertexAttributesMap_t& vertexAttributes) { vertexAttributes_ = vertexAttributes; // Calculate offset and array index depending on vertex attributes provided by the user map<size_t, VertexAttributes_t> attributesFromIndex; VertexAttributesMap_t::iterator it = vertexAttributes_.begin(); for (; it != vertexAttributes_.end(); ++it) { attributesFromIndex[it->second] = it->first; } bufferObjects_ = new BufferObject* [surfaces_.size()]; BufferUsage_t bufferUsage = (meshType_ == MESH_TYPE_STATIC) ? BUFFER_USAGE_STATIC : BUFFER_USAGE_DYNAMIC; for (size_t i = 0; i < surfaces_.size(); i++) { bufferObjects_[i] = Renderer::GetInstance()->GetBufferObjectManager()->CreateBufferObject(vertexAttributes_, bufferUsage); BufferObject* bufferObject = bufferObjects_[i]; // Interleave the data vector<float> data; size_t sizeToReserve = surfaces_[i]->numVertices * 3 + surfaces_[i]->numNormals * 3 + surfaces_[i]->numTexCoords * 2 + surfaces_[i]->numTangents * 3; // Add the data for the bones since it will be skinned on the GPU if (meshType_ == MESH_TYPE_STATIC) { sizeToReserve += surfaces_[i]->numBones * 4 + surfaces_[i]->numWeights * 4; } data.reserve(sizeToReserve); bool hasNormals = surfaces_[i]->numNormals > 0; bool hasTexCoords = surfaces_[i]->numTexCoords > 0; bool hasTangents = surfaces_[i]->numTangents > 0; bool hasBones = surfaces_[i]->numBones > 0; bool hasWeights = surfaces_[i]->numWeights > 0; Vector3 vertex; for (size_t j = 0; j < surfaces_[i]->numVertices; j++) { map<size_t, VertexAttributes_t>::iterator v_it = attributesFromIndex.begin(); for (; v_it != attributesFromIndex.end(); ++v_it) { switch (v_it->second) { case VERTEX_ATTRIBUTES_POSITION: vertex = surfaces_[i]->vertices[j]; data.push_back(vertex.x); data.push_back(vertex.y); data.push_back(vertex.z); break; case VERTEX_ATTRIBUTES_NORMAL: if (hasNormals) { Vector3& normal = surfaces_[i]->normals[j]; data.push_back(normal.x); data.push_back(normal.y); data.push_back(normal.z); } break; case VERTEX_ATTRIBUTES_TEX_COORDS: if (hasTexCoords) { Vector2& texCoords = surfaces_[i]->texCoords[j]; data.push_back(texCoords.x); data.push_back(texCoords.y); } break; case VERTEX_ATTRIBUTES_TANGENT: if (hasTangents) { Vector3& tangents = surfaces_[i]->tangents[j]; data.push_back(tangents.x); data.push_back(tangents.y); data.push_back(tangents.z); } break; case VERTEX_ATTRIBUTES_BONES: if (hasBones) { Vector4& bones = surfaces_[i]->bones[j]; data.push_back(bones.x); data.push_back(bones.y); data.push_back(bones.z); data.push_back(bones.w); } break; case VERTEX_ATTRIBUTES_WEIGHTS: if (hasWeights) { Vector4& weights = surfaces_[i]->weights[j]; data.push_back(weights.x); data.push_back(weights.y); data.push_back(weights.z); data.push_back(weights.w); } break; } } } int presentVertexAttributes = 0; if (hasNormals) { presentVertexAttributes |= VERTEX_ATTRIBUTES_NORMAL; } if (hasTexCoords) { presentVertexAttributes |= VERTEX_ATTRIBUTES_TEX_COORDS; } if (hasTangents) { presentVertexAttributes |= VERTEX_ATTRIBUTES_TANGENT; } if (hasBones) { presentVertexAttributes |= VERTEX_ATTRIBUTES_BONES; } if (hasWeights) { presentVertexAttributes |= VERTEX_ATTRIBUTES_WEIGHTS; } if (bufferObject->SetVertexData(data, presentVertexAttributes) != BUFFER_OBJECT_ERROR_NONE) { Logger::GetInstance()->Error("The vertex attributes are not all present"); FreeMeshMemory(); break; } bufferObject->SetIndexData(surfaces_[i]->indices, surfaces_[i]->numIndices); } }