void C4FoWDrawWireframeStrategy::End(C4ShaderCall& call) { // If we have nothing to draw (e.g. directly after initialization), abort early. if (vertices.empty()) return; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Upload vertices glBindBuffer(GL_ARRAY_BUFFER, vbo); if (vbo_size < vertices.size()) { glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STREAM_DRAW); vbo_size = vertices.size(); } else { glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]); } glEnableVertexAttribArray(call.GetAttribute(C4FoWRSA_Position)); glEnableVertexAttribArray(call.GetAttribute(C4FoWRSA_Color)); glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Position), 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, x))); glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Color), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, r))); // Set Y offset for vertex const float y_offset[] = { 0.0f, 0.0f }; call.SetUniform2fv(C4FoWRSU_VertexOffset, 1, y_offset); glDrawElements(GL_TRIANGLES, triangulator.GetNIndices(), GL_UNSIGNED_INT, triangulator.GetIndices()); // Reset GL state glDisableVertexAttribArray(call.GetAttribute(C4FoWRSA_Position)); glDisableVertexAttribArray(call.GetAttribute(C4FoWRSA_Color)); glBindBuffer(GL_ARRAY_BUFFER, 0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Assume the capacity stays the same: vertices.resize(0); C4FoWDrawStrategy::End(call); }
void C4ParticleChunk::Draw(C4TargetFacet cgo, C4Object *obj, C4ShaderCall& call, int texUnit, const StdProjectionMatrix& modelview) { if (particleCount == 0) return; const int stride = sizeof(C4Particle::DrawingData::Vertex); assert(sourceDefinition && "No source definition assigned to particle chunk."); C4TexRef *textureRef = &sourceDefinition->Gfx.GetFace().textures[0]; assert(textureRef != 0 && "Particle definition had no texture assigned."); // use a relative offset? // (note the normal matrix is unaffected by this) if ((attachment & C4ATTACH_MoveRelative) && (obj != 0)) { StdProjectionMatrix new_modelview(modelview); Translate(new_modelview, fixtof(obj->GetFixedX()), fixtof(obj->GetFixedY()), 0.0f); call.SetUniformMatrix4x4(C4SSU_ModelViewMatrix, new_modelview); } else { call.SetUniformMatrix4x4(C4SSU_ModelViewMatrix, modelview); } // enable additive blending for particles with that blit mode glBlendFunc(GL_SRC_ALPHA, (blitMode & C4GFXBLIT_ADDITIVE) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA); glActiveTexture(texUnit); glBindTexture(GL_TEXTURE_2D, textureRef->texName); // generate the buffer as necessary if (drawingDataVertexBufferObject == 0) { // clear up old data ClearBufferObjects(); // generate new buffer objects glGenBuffers(1, &drawingDataVertexBufferObject); assert (drawingDataVertexBufferObject != 0 && "Could not generate OpenGL buffer object."); // Immediately bind the buffer. // glVertexAttribPointer requires a valid GL_ARRAY_BUFFER to be bound and we need the buffer to be created for glObjectLabel. glBindBuffer(GL_ARRAY_BUFFER, drawingDataVertexBufferObject); #ifdef GL_KHR_debug if (glObjectLabel) glObjectLabel(GL_BUFFER, drawingDataVertexBufferObject, -1, "<particles>/VBO"); #endif // generate new VAO ID drawingDataVertexArraysObject = pGL->GenVAOID(); assert (drawingDataVertexArraysObject != 0 && "Could not generate a VAO ID."); } // Push the new vertex data glBindBuffer(GL_ARRAY_BUFFER, drawingDataVertexBufferObject); glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(C4Particle::DrawingData::Vertex) * particleCount, &vertexCoordinates[0], GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // set up the vertex array structure GLuint vao; const bool has_vao = pGL->GetVAO(drawingDataVertexArraysObject, vao); glBindVertexArray(vao); assert ((drawingDataVertexBufferObject != 0) && "No buffer object has been created yet."); assert ((drawingDataVertexArraysObject != 0) && "No vertex arrays object has been created yet."); if (!has_vao) { glBindBuffer(GL_ARRAY_BUFFER, drawingDataVertexBufferObject); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ::Particles.GetIBO()); #ifdef GL_KHR_debug if (glObjectLabel) glObjectLabel(GL_VERTEX_ARRAY, vao, -1, "<particles>/VAO"); #endif glEnableVertexAttribArray(call.GetAttribute(C4SSA_Position)); glEnableVertexAttribArray(call.GetAttribute(C4SSA_Color)); glEnableVertexAttribArray(call.GetAttribute(C4SSA_TexCoord)); glVertexAttribPointer(call.GetAttribute(C4SSA_Position), 2, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<GLvoid*>(offsetof(C4Particle::DrawingData::Vertex, x))); glVertexAttribPointer(call.GetAttribute(C4SSA_TexCoord), 2, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<GLvoid*>(offsetof(C4Particle::DrawingData::Vertex, u))); glVertexAttribPointer(call.GetAttribute(C4SSA_Color), 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<GLvoid*>(offsetof(C4Particle::DrawingData::Vertex, r))); } glDrawElements(GL_TRIANGLE_STRIP, static_cast<GLsizei> (5 * particleCount), GL_UNSIGNED_INT, 0); // reset buffer data glBindVertexArray(0); }
void C4FoWDrawLightTextureStrategy::End(C4ShaderCall& call) { // If we have nothing to draw (e.g. directly after initialization), abort early. if (vertices.empty()) return; // Upload vertices glBindBuffer(GL_ARRAY_BUFFER, vbo); if (vbo_size < vertices.size()) { glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_DYNAMIC_DRAW); vbo_size = vertices.size(); } else { glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]); } // Region dimensions const float width = region->getSurfaceWidth(); const float height = region->getSurfaceHeight() / 2.0; // Set Y offset for vertex float y_offset[] = { 0.0f, 0.0f }; call.SetUniform2fv(C4FoWRSU_VertexOffset, 1, y_offset); // Enable scissor test to only draw in upper or lower half of texture glEnable(GL_SCISSOR_TEST); glScissor(0, height, width, height); // Setup state for 1st pass glEnableVertexAttribArray(call.GetAttribute(C4FoWRSA_Position)); glEnableVertexAttribArray(call.GetAttribute(C4FoWRSA_Color)); glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Position), 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, x))); glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Color), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, r1))); // Set up blend equation, see C4FoWDrawLightTextureStrategy::DrawVertex // for details. glBlendFunc(GL_ONE, GL_ONE); glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); // Render 1st pass glDrawElements(GL_TRIANGLES, triangulator.GetNIndices(), GL_UNSIGNED_INT, triangulator.GetIndices()); // Prepare state for 2nd pass glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Color), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, r2))); // Render 2nd pass glDrawElements(GL_TRIANGLES, triangulator.GetNIndices(), GL_UNSIGNED_INT, triangulator.GetIndices()); // Prepare state for 3rd pass (color pass) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); glScissor(0, 0, width, height); glVertexAttribPointer(call.GetAttribute(C4FoWRSA_Color), 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<const uint8_t*>(offsetof(Vertex, r3))); y_offset[1] = height; call.SetUniform2fv(C4FoWRSU_VertexOffset, 1, y_offset); // Render 3rd pass glDrawElements(GL_TRIANGLES, triangulator.GetNIndices(), GL_UNSIGNED_INT, triangulator.GetIndices()); // Reset GL state glDisableVertexAttribArray(call.GetAttribute(C4FoWRSA_Position)); glDisableVertexAttribArray(call.GetAttribute(C4FoWRSA_Color)); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_SCISSOR_TEST); // Assume the capacity stays the same: vertices.resize(0); C4FoWDrawStrategy::End(call); }