diff --git a/src/engine/renderer/opengl/renderer_opengl.cc b/src/engine/renderer/opengl/renderer_opengl.cc index cb4562d..192b793 100644 --- a/src/engine/renderer/opengl/renderer_opengl.cc +++ b/src/engine/renderer/opengl/renderer_opengl.cc @@ -26,6 +26,9 @@ constexpr GLenum kGlDataType[eng::kDataType_Max] = { GL_UNSIGNED_BYTE, GL_FLOAT, GL_INT, GL_SHORT, GL_UNSIGNED_INT, GL_UNSIGNED_SHORT}; +constexpr GLboolean kGlNormalize[eng::kDataType_Max] = { + GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE}; + const std::string kAttributeNames[eng::kAttribType_Max] = { "in_color", "in_normal", "in_position", "in_tex_coord"}; @@ -132,11 +135,16 @@ void RendererOpenGL::DestroyGeometry(uint64_t resource_id) { geometries_.erase(it); } -void RendererOpenGL::Draw(uint64_t resource_id) { +void RendererOpenGL::Draw(uint64_t resource_id, + uint64_t num_indices, + uint64_t start_offset) { auto it = geometries_.find(resource_id); if (it == geometries_.end()) return; + if (num_indices == 0) + num_indices = it->second.num_indices; + // Set up the vertex data. if (it->second.vertex_array_id) glBindVertexArray(it->second.vertex_array_id); @@ -152,14 +160,14 @@ void RendererOpenGL::Draw(uint64_t resource_id) { (const GLvoid*)e.vertex_offset); } - if (it->second.num_indices > 0) + if (num_indices > 0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->second.index_buffer_id); } // Draw the primitive. - if (it->second.num_indices > 0) - glDrawElements(it->second.primitive, it->second.num_indices, - it->second.index_type, NULL); + if (num_indices > 0) + glDrawElements(it->second.primitive, num_indices, it->second.index_type, + (void*)(intptr_t)(start_offset * sizeof(unsigned short))); else glDrawArrays(it->second.primitive, 0, it->second.num_vertices); @@ -446,7 +454,7 @@ bool RendererOpenGL::InitCommon() { #if 0 LOG(0) << " extensions:"; for (auto& ext : extensions) - LOG(0) << " " << ext.c_str()); + LOG(0) << " " << ext.c_str(); #endif // Check for supported texture compression extensions. @@ -465,7 +473,8 @@ bool RendererOpenGL::InitCommon() { extensions.find("GL_ATI_texture_compression_atitc") != extensions.end()) texture_compression_.atc = true; - if (extensions.find("GL_OES_vertex_array_object") != extensions.end()) { + if (extensions.find("GL_OES_vertex_array_object") != extensions.end() || + extensions.find("GL_ARB_vertex_array_object") != extensions.end()) { // This extension seems to be broken on older PowerVR drivers. if (!strstr(renderer, "PowerVR SGX 53") && !strstr(renderer, "PowerVR SGX 54") && @@ -555,8 +564,9 @@ bool RendererOpenGL::SetupVertexLayout( if (use_vao) { // This will be saved into the vertex array object. glEnableVertexAttribArray(attribute_index); - glVertexAttribPointer(attribute_index, num_elements, type, GL_FALSE, - vertex_size, (const GLvoid*)vertex_offset); + glVertexAttribPointer(attribute_index, num_elements, type, + kGlNormalize[data_type], vertex_size, + (const GLvoid*)vertex_offset); } else { // Need to keep this information for when rendering. GeometryOpenGL::Element element; diff --git a/src/engine/renderer/opengl/renderer_opengl.h b/src/engine/renderer/opengl/renderer_opengl.h index a6cce5b..ba82232 100644 --- a/src/engine/renderer/opengl/renderer_opengl.h +++ b/src/engine/renderer/opengl/renderer_opengl.h @@ -33,7 +33,9 @@ class RendererOpenGL final : public Renderer { uint64_t CreateGeometry(std::unique_ptr mesh) final; void DestroyGeometry(uint64_t resource_id) final; - void Draw(uint64_t resource_id) final; + void Draw(uint64_t resource_id, + uint64_t num_indices = 0, + uint64_t start_offset = 0) final; uint64_t CreateTexture() final; void UpdateTexture(uint64_t resource_id, std::unique_ptr image) final; diff --git a/src/engine/renderer/renderer.h b/src/engine/renderer/renderer.h index 16831a4..ddb2568 100644 --- a/src/engine/renderer/renderer.h +++ b/src/engine/renderer/renderer.h @@ -40,7 +40,9 @@ class Renderer { virtual uint64_t CreateGeometry(std::unique_ptr mesh) = 0; virtual void DestroyGeometry(uint64_t resource_id) = 0; - virtual void Draw(uint64_t resource_id) = 0; + virtual void Draw(uint64_t resource_id, + uint64_t num_indices = 0, + uint64_t start_offset = 0) = 0; virtual uint64_t CreateTexture() = 0; virtual void UpdateTexture(uint64_t resource_id, diff --git a/src/engine/renderer/vulkan/renderer_vulkan.cc b/src/engine/renderer/vulkan/renderer_vulkan.cc index fce8d84..be3ed73 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.cc +++ b/src/engine/renderer/vulkan/renderer_vulkan.cc @@ -155,10 +155,10 @@ constexpr VkPrimitiveTopology kVkPrimitiveType[eng::kPrimitive_Max] = { constexpr VkFormat kVkDataType[eng::kDataType_Max][4] = { { - VK_FORMAT_R8_UINT, - VK_FORMAT_R8G8_UINT, - VK_FORMAT_R8G8B8_UINT, - VK_FORMAT_R8G8B8A8_UINT, + VK_FORMAT_R8_UNORM, + VK_FORMAT_R8G8_UNORM, + VK_FORMAT_R8G8B8_UNORM, + VK_FORMAT_R8G8B8A8_UNORM, }, { VK_FORMAT_R32_SFLOAT, @@ -400,7 +400,8 @@ uint64_t RendererVulkan::CreateGeometry(std::unique_ptr mesh) { if (mesh->GetIndices()) { geometry.num_indices = mesh->num_indices(); geometry.index_type = GetIndexType(mesh->index_description()); - index_data_size = mesh->GetIndexSize() * geometry.num_indices; + geometry.index_type_size = mesh->GetIndexSize(); + index_data_size = geometry.index_type_size * geometry.num_indices; } size_t data_size = vertex_data_size + index_data_size; @@ -414,11 +415,11 @@ uint64_t RendererVulkan::CreateGeometry(std::unique_ptr mesh) { std::get<0>(geometry.buffer), 0, mesh->GetVertices(), vertex_data_size)); if (geometry.num_indices > 0) { - geometry.indices_offset = vertex_data_size; - task_runner_.PostTask( - HERE, std::bind(&RendererVulkan::UpdateBuffer, this, - std::get<0>(geometry.buffer), geometry.indices_offset, - mesh->GetIndices(), index_data_size)); + geometry.index_data_offset = vertex_data_size; + task_runner_.PostTask(HERE, std::bind(&RendererVulkan::UpdateBuffer, this, + std::get<0>(geometry.buffer), + geometry.index_data_offset, + mesh->GetIndices(), index_data_size)); } task_runner_.PostTask(HERE, std::bind(&RendererVulkan::BufferMemoryBarrier, this, @@ -442,20 +443,27 @@ void RendererVulkan::DestroyGeometry(uint64_t resource_id) { geometries_.erase(it); } -void RendererVulkan::Draw(uint64_t resource_id) { +void RendererVulkan::Draw(uint64_t resource_id, + uint64_t num_indices, + uint64_t start_offset) { auto it = geometries_.find(resource_id); if (it == geometries_.end()) return; + uint64_t data_offset = start_offset * it->second.index_type_size; + if (num_indices == 0) + num_indices = it->second.num_indices; + VkDeviceSize offset = 0; vkCmdBindVertexBuffers(frames_[current_frame_].draw_command_buffer, 0, 1, &std::get<0>(it->second.buffer), &offset); - if (it->second.num_indices > 0) { + if (num_indices > 0) { vkCmdBindIndexBuffer(frames_[current_frame_].draw_command_buffer, std::get<0>(it->second.buffer), - it->second.indices_offset, it->second.index_type); - vkCmdDrawIndexed(frames_[current_frame_].draw_command_buffer, - it->second.num_indices, 1, 0, 0, 0); + it->second.index_data_offset + data_offset, + it->second.index_type); + vkCmdDrawIndexed(frames_[current_frame_].draw_command_buffer, num_indices, + 1, 0, 0, 0); } else { vkCmdDraw(frames_[current_frame_].draw_command_buffer, it->second.num_vertices, 1, 0, 0); diff --git a/src/engine/renderer/vulkan/renderer_vulkan.h b/src/engine/renderer/vulkan/renderer_vulkan.h index df07dc5..9d749ce 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.h +++ b/src/engine/renderer/vulkan/renderer_vulkan.h @@ -35,7 +35,9 @@ class RendererVulkan final : public Renderer { uint64_t CreateGeometry(std::unique_ptr mesh) final; void DestroyGeometry(uint64_t resource_id) final; - void Draw(uint64_t resource_id) final; + void Draw(uint64_t resource_id, + uint64_t num_indices = 0, + uint64_t start_offset = 0) final; uint64_t CreateTexture() final; void UpdateTexture(uint64_t resource_id, std::unique_ptr image) final; @@ -101,7 +103,8 @@ class RendererVulkan final : public Renderer { Buffer buffer; uint32_t num_vertices = 0; uint32_t num_indices = 0; - uint64_t indices_offset = 0; + uint64_t index_data_offset = 0; + uint64_t index_type_size = 0; VkIndexType index_type = VK_INDEX_TYPE_UINT16; };