-
Notifications
You must be signed in to change notification settings - Fork 22
GPU Tessellation Tier 1 #900
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
NoahBussingerUbique
wants to merge
24
commits into
main
Choose a base branch
from
feature/gpu-tessellation-tier1
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,990
−110
Open
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
5f61af8
Add unfinished quad gpu tesselation
NoahBussingerUbique d465d5b
Change curving from normalize to sin cos
NoahBussingerUbique 34aed00
Quad tessellation blend and non 3d
NoahBussingerUbique 8c79523
Refactor and unfinished polygon mask tessellation
NoahBussingerUbique 5e686b7
Partially working polygon mask tessellation
NoahBussingerUbique 65d716d
Complete polygon mask tessellation
NoahBussingerUbique 80bb224
Begin android quad tessellation
NoahBussingerUbique bd43bad
Complete android quad tessellation
NoahBussingerUbique c05337f
Complete and improve polygon tessellation
NoahBussingerUbique f7ce250
Begin clean up
NoahBussingerUbique 904f23f
Remove elevation test and fix 2d subdivision
NoahBussingerUbique 999af35
Refactor vertex structs and properties
NoahBussingerUbique a4b7f01
Refactor is3d and subdivisionFactor handling
NoahBussingerUbique 392b619
Remove comments and add wireframe macro
NoahBussingerUbique dbabf12
Port polygon layer to tessellation
NoahBussingerUbique e87eb01
Optimize tessellation shaders with reordering
NoahBussingerUbique 95bf953
Optimize tessellation shaders with halfs
NoahBussingerUbique b26420d
Split tessellation and legacy path by compile time flag
NoahBussingerUbique 1d89e9d
Minor improvements in android backend
NoahBussingerUbique dfd1d3b
Prevent tessellation on ios simulator
NoahBussingerUbique 8083aad
Rename tessellation constants
NoahBussingerUbique a605587
Consistent subdivision factor space
NoahBussingerUbique 8f22cb0
Fix IconLayer subdivision error
NoahBussingerUbique 7ce8fcf
Disable tessellation in 2d cases with hardware support
NoahBussingerUbique File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
212 changes: 212 additions & 0 deletions
212
android/src/main/cpp/graphics/objects/Polygon2dTessellatedOpenGl.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| /* | ||
| * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch> | ||
| * | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| * | ||
| * SPDX-License-Identifier: MPL-2.0 | ||
| */ | ||
|
|
||
| #include "Polygon2dTessellatedOpenGl.h" | ||
| #include "OpenGlHelper.h" | ||
| #include <cstring> | ||
|
|
||
| Polygon2dTessellatedOpenGl::Polygon2dTessellatedOpenGl(const std::shared_ptr<::BaseShaderProgramOpenGl> &shader) | ||
| : shaderProgram(shader) {} | ||
|
|
||
| std::shared_ptr<GraphicsObjectInterface> Polygon2dTessellatedOpenGl::asGraphicsObject() { return shared_from_this(); } | ||
|
|
||
| std::shared_ptr<MaskingObjectInterface> Polygon2dTessellatedOpenGl::asMaskingObject() { return shared_from_this(); } | ||
|
|
||
| bool Polygon2dTessellatedOpenGl::isReady() { return ready; } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::setSubdivisionFactor(int32_t factor) { | ||
| std::lock_guard<std::recursive_mutex> lock(dataMutex); | ||
| if (factor != subdivisionFactor) { | ||
| subdivisionFactor = factor; | ||
| } | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::setVertices(const ::SharedBytes & vertices_, const ::SharedBytes & indices_, const ::Vec3D & origin, bool is3d) { | ||
| std::lock_guard<std::recursive_mutex> lock(dataMutex); | ||
| ready = false; | ||
| dataReady = false; | ||
|
|
||
| indices.resize(indices_.elementCount); | ||
| vertices.resize(vertices_.elementCount); | ||
| polygonOrigin = origin; | ||
|
|
||
| this->is3d = is3d; | ||
|
|
||
| if (indices_.elementCount > 0) { | ||
| std::memcpy(indices.data(), (void *)indices_.address, indices_.elementCount * indices_.bytesPerElement); | ||
| } | ||
|
|
||
| if (vertices_.elementCount > 0) { | ||
| std::memcpy(vertices.data(), (void *)vertices_.address, | ||
| vertices_.elementCount * vertices_.bytesPerElement); | ||
| } | ||
|
|
||
| dataReady = true; | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::setup(const std::shared_ptr<::RenderingContextInterface> &context) { | ||
| std::lock_guard<std::recursive_mutex> lock(dataMutex); | ||
| if (ready || !dataReady) { | ||
| return; | ||
| } | ||
|
|
||
| std::shared_ptr<OpenGlContext> openGlContext = std::static_pointer_cast<OpenGlContext>(context); | ||
| programName = shaderProgram->getProgramName(); | ||
| program = openGlContext->getProgram(programName); | ||
| if (program == 0) { | ||
| shaderProgram->setupProgram(openGlContext); | ||
| program = openGlContext->getProgram(programName); | ||
| } | ||
|
|
||
| prepareGlData(program); | ||
| ready = true; | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::prepareGlData(int program) { | ||
| glUseProgram(program); | ||
|
|
||
| if (!glDataBuffersGenerated) { | ||
| glGenVertexArrays(1, &vao); | ||
| } | ||
| glBindVertexArray(vao); | ||
|
|
||
| positionHandle = glGetAttribLocation(program, "vPosition"); | ||
| frameCoordHandle = glGetAttribLocation(program, "vFrameCoord"); | ||
| if (!glDataBuffersGenerated) { | ||
| glGenBuffers(1, &vertexBuffer); | ||
| } | ||
| glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); | ||
| glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), &vertices[0], GL_STATIC_DRAW); | ||
|
|
||
| size_t stride = sizeof(GLfloat) * 5; | ||
| glEnableVertexAttribArray(positionHandle); | ||
| glVertexAttribPointer(positionHandle, 3, GL_FLOAT, false, stride, nullptr); | ||
| glEnableVertexAttribArray(frameCoordHandle); | ||
| glVertexAttribPointer(frameCoordHandle, 2, GL_FLOAT, false, stride, (float*)(sizeof(GLfloat) * 3)); | ||
|
|
||
| glBindBuffer(GL_ARRAY_BUFFER, 0); | ||
|
|
||
| if (!glDataBuffersGenerated) { | ||
| glGenBuffers(1, &indexBuffer); | ||
| } | ||
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); | ||
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * indices.size(), &indices[0], GL_STATIC_DRAW); | ||
|
|
||
| glBindVertexArray(0); | ||
|
|
||
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | ||
|
|
||
| mMatrixHandle = glGetUniformLocation(program, "umMatrix"); | ||
| originOffsetHandle = glGetUniformLocation(program, "uOriginOffset"); | ||
| subdivisionFactorHandle = glGetUniformLocation(program, "uSubdivisionFactor"); | ||
| originHandle = glGetUniformLocation(program, "uOrigin"); | ||
| is3dHandle = glGetUniformLocation(program, "uIs3d"); | ||
|
|
||
| glDataBuffersGenerated = true; | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::clear() { | ||
| std::lock_guard<std::recursive_mutex> lock(dataMutex); | ||
| if (ready) { | ||
| removeGlBuffers(); | ||
| ready = false; | ||
| } | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::removeGlBuffers() { | ||
| if (glDataBuffersGenerated) { | ||
| glDeleteBuffers(1, &vertexBuffer); | ||
| glDeleteBuffers(1, &indexBuffer); | ||
| glDeleteVertexArrays(1, &vao); | ||
| glDataBuffersGenerated = false; | ||
| } | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::setIsInverseMasked(bool inversed) { isMaskInversed = inversed; } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::render(const std::shared_ptr<::RenderingContextInterface> &context, const RenderPassConfig &renderPass, | ||
| int64_t vpMatrix, int64_t mMatrix, const ::Vec3D &origin, bool isMasked, | ||
| double screenPixelAsRealMeterFactor, bool isScreenSpaceCoords) { | ||
| std::lock_guard<std::recursive_mutex> lock(dataMutex); | ||
| if (!ready || !shaderProgram->isRenderable()) { | ||
| return; | ||
| } | ||
|
|
||
| std::shared_ptr<OpenGlContext> openGlContext = std::static_pointer_cast<OpenGlContext>(context); | ||
|
|
||
| GLuint stencilMask = 0; | ||
| GLuint validTarget = 0; | ||
| GLenum zpass = GL_KEEP; | ||
| if (isMasked) { | ||
| stencilMask += 128; | ||
| validTarget = isMaskInversed ? 0 : 128; | ||
| } | ||
| if (renderPass.isPassMasked) { | ||
| stencilMask += 127; | ||
| zpass = GL_INCR; | ||
| } | ||
|
|
||
| if (stencilMask != 0) { | ||
| glStencilFunc(GL_EQUAL, validTarget, stencilMask); | ||
| glStencilOp(GL_KEEP, GL_KEEP, zpass); | ||
| } | ||
|
|
||
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||
|
|
||
| drawPolygon(openGlContext, program, vpMatrix, mMatrix, origin, isScreenSpaceCoords); | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::drawPolygon(const std::shared_ptr<::RenderingContextInterface> &context, int program, int64_t vpMatrix, | ||
| int64_t mMatrix, const Vec3D &origin, bool isScreenSpaceCoords) { | ||
| std::lock_guard<std::recursive_mutex> lock(dataMutex); | ||
| // Add program to OpenGL environment | ||
| glUseProgram(program); | ||
| glBindVertexArray(vao); | ||
|
|
||
| shaderProgram->preRender(context, isScreenSpaceCoords); | ||
|
|
||
| if(shaderProgram->usesModelMatrix()) { | ||
| glUniformMatrix4fv(mMatrixHandle, 1, false, (GLfloat *) mMatrix); | ||
| } | ||
|
|
||
| glUniform4f(originOffsetHandle, polygonOrigin.x - origin.x, polygonOrigin.y - origin.y, polygonOrigin.z - origin.z, 0.0); | ||
|
|
||
| glPatchParameteri(GL_PATCH_VERTICES, 3); | ||
|
|
||
| glUniform1i(subdivisionFactorHandle, pow(2, subdivisionFactor)); | ||
|
|
||
| glUniform4f(originHandle, origin.x, origin.y, origin.z, 0.0); | ||
|
|
||
| glUniform1i(is3dHandle, is3d); | ||
|
|
||
| glDrawElements(GL_PATCHES, (unsigned short)indices.size(), GL_UNSIGNED_SHORT, nullptr); | ||
|
|
||
| glBindVertexArray(0); | ||
|
|
||
| glDisable(GL_BLEND); | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::renderAsMask(const std::shared_ptr<::RenderingContextInterface> &context, | ||
| const ::RenderPassConfig &renderPass, int64_t vpMatrix, int64_t mMatrix, | ||
| const ::Vec3D &origin, double screenPixelAsRealMeterFactor, bool isScreenSpaceCoords) { | ||
| if (!ready) { | ||
| return; | ||
| } | ||
|
|
||
| std::shared_ptr<OpenGlContext> openGlContext = std::static_pointer_cast<OpenGlContext>(context); | ||
|
|
||
| glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); | ||
| drawPolygon(openGlContext, program, vpMatrix, mMatrix, origin, isScreenSpaceCoords); | ||
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||
| } | ||
|
|
||
| void Polygon2dTessellatedOpenGl::setDebugLabel(const std::string &label) { | ||
| // not used | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be confusing that the tesselated / non-tesselated types are mixed behind the same interface. We need to manually keep track of where a tesselated object is used.
Would it be an option to have a separate type hierarchy for the tesselated types, or does that make integration much more complicated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
Thinking about it, the tessellated interfaces which would extend the normal ones would be almost empty though. The only change i did to the interfaces i think was the addition of the setSubdivisionFactor to the polygon interface. The reason i did this was for consistency with the quad interface, there for some reason the subdivision gets done on the level of the metal/opengl backend.