Commit 1360526f by Philipp Adolf

Add edge computation shader

parents 188a8f55 09a808ae
......@@ -370,8 +370,8 @@ void Mesh::renderMesh(QOpenGLShaderProgram *shader, int index)
// Draw Vertex Array
f->glBindBuffer(GL_ARRAY_BUFFER, entries[index].VB_handle);
f->glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
f->glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12); //12
f->glVertexAttribPointer(uvIndex, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)24); // 12+12
f->glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)16); //3*4+4
f->glVertexAttribPointer(uvIndex, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)32); // 12+4+12+4
f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, entries[index].IB_handle);
......
......@@ -17,8 +17,14 @@
struct Vertex
{
QVector3D pos;
float padding0;
QVector3D normal;
float padding1;
QVector2D tex;
QVector2D padding2;
Vertex(){}
......
......@@ -5,6 +5,6 @@
<file>subdivide.tcs</file>
<file>subdivide.tes</file>
<file>subdivide.vert</file>
<file>subdivision.compute</file>
<file>subdivision-edge.compute</file>
</qresource>
</RCC>
#version 430 core
layout (local_size_x = 1) in;
struct Vertex {
vec3 pos;
vec3 norm;
vec2 uv;
};
layout(std430, binding=0) readonly buffer Vertices {
Vertex vertices[];
};
layout(std430, binding=1) readonly buffer EdgeIndices {
unsigned int indices[][4];
};
layout(std430, binding=2) writeonly buffer Output {
Vertex edges[];
};
void main(){
edges[gl_GlobalInvocationID.x].norm = vec3(0.0, 0.0, 0.0);
edges[gl_GlobalInvocationID.x].uv = vec2(0.0, 0.0);
edges[gl_GlobalInvocationID.x].pos = 3.0/8.0 * (vertices[indices[gl_GlobalInvocationID.x][0]].pos + vertices[indices[gl_GlobalInvocationID.x][1]].pos) + 1.0/8.0 * (vertices[indices[gl_GlobalInvocationID.x][2]].pos + vertices[indices[gl_GlobalInvocationID.y][3]].pos);
}
#version 430 core
layout (local_size_x = 2) in;
layout(std430, binding=0) readonly buffer Input {
float offset;
};
layout(std430, binding=1) writeonly buffer Output {
float data[];
};
void main(){
data[gl_GlobalInvocationID.x] = 100 * gl_GlobalInvocationID.x + gl_LocalInvocationID.x + offset;
}
......@@ -7,11 +7,11 @@ Subdivision::Subdivision(QOpenGLFunctions_4_3_Core *f)
Subdivision::~Subdivision()
{
delete shader;
delete edgeShader;
}
void Subdivision::init() {
shader = initComputeShaderProgram();
edgeShader = initEdgeComputeShaderProgram();
}
QVector<unsigned int> Subdivision::fillVector(unsigned int a, unsigned int b, unsigned int c,unsigned int d){
......@@ -23,8 +23,8 @@ QVector<unsigned int> Subdivision::fillVector(unsigned int a, unsigned int b, un
return x;
}
QOpenGLShaderProgram *Subdivision::initComputeShaderProgram(){
QString source = QLatin1String(":/subdivision.compute");
QOpenGLShaderProgram *Subdivision::initEdgeComputeShaderProgram(){
QString source = QLatin1String(":/subdivision-edge.compute");
qDebug()<<"Compiling compute shader ...";
QOpenGLShader *computeShader = new QOpenGLShader(QOpenGLShader::Compute);
......@@ -47,12 +47,13 @@ QOpenGLShaderProgram *Subdivision::initComputeShaderProgram(){
}
Mesh *Subdivision::subdivide(Mesh *mesh) {
precomputeTables(mesh);
runShader(mesh);
QVector<QVector<unsigned int> > edgeIndices;
precomputeTables(mesh, edgeIndices);
runShader(mesh, edgeIndices);
return NULL;
}
void Subdivision::precomputeTables(Mesh *mesh) {
void Subdivision::precomputeTables(Mesh *mesh, QVector<QVector<unsigned int> > &edgeIndices_base) {
Mesh::Node root = mesh->getRootNode();
int firstMeshEntryIndex = -1;
......@@ -73,7 +74,6 @@ void Subdivision::precomputeTables(Mesh *mesh) {
//compute edge table
//Format: first two entries: edge vertices. last two entries: distant vertices.
QVector<QVector<unsigned int> > edgeIndices_base;
for (int i = 0; i < ib.length(); i+=3){
//schaue alle dreiecke an
......@@ -265,33 +265,48 @@ void Subdivision::precomputeTables(Mesh *mesh) {
}
void Subdivision::runShader(Mesh *mesh) {
/*
* This shader will set the output buffer to its global ID times hundred + the local id + offset.
*
* So, for offset = 0 we will get 0, 101, 200, 301 and so on as there's two threads in a local group.
*/
void Subdivision::runShader(Mesh *mesh, QVector<QVector<unsigned int> > &edgeIndices) {
qDebug()<<"Running compute shader";
int num = 6 * 2; // must be a multiple of two as we do not handle the other case
GLfloat offset = 3.0f;
shader->bind();
Mesh::Node root = mesh->getRootNode();
int firstMeshEntryIndex = -1;
bool meshExists = root.getFirstMeshIndex(firstMeshEntryIndex);
if (!meshExists){
qDebug()<<"No Mesh found. Abort shader execution.";
return;
}
qDebug()<<"Mesh found. Index:"<<firstMeshEntryIndex;
Mesh::MeshEntry *firstMeshEntry = mesh->getMeshEntry(firstMeshEntryIndex);
GLuint vb_handle = firstMeshEntry->VB_handle;
QVector<Vertex> vb = firstMeshEntry->getVertexBuffer();
edgeShader->bind();
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vb_handle);
GLuint *edgeIDs = new GLuint[edgeIndices.size() * 4];
for (uint i = 0; i < edgeIndices.size(); i++) {
for (uint j = 0; j < 4; j++) {
edgeIDs[4 * i + j] = edgeIndices[i][j];
}
}
// Create an input buffer and set it to the value of offset
GLuint offsetBufferID;
f->glGenBuffers(1, &offsetBufferID);
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, offsetBufferID);
f->glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &offset, GL_DYNAMIC_DRAW);
GLuint indicesID;
f->glGenBuffers(1, &indicesID);
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, indicesID);
f->glBufferData(GL_SHADER_STORAGE_BUFFER, edgeIndices.size() * sizeof(GLuint) * 4, &edgeIDs[0], GL_DYNAMIC_DRAW);
delete edgeIDs;
// Create an output buffer
GLuint bufferID;
f->glGenBuffers(1, &bufferID);
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, bufferID);
f->glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat) * num, NULL, GL_DYNAMIC_DRAW);
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, bufferID);
f->glBufferData(GL_SHADER_STORAGE_BUFFER, edgeIndices.size() * sizeof(Vertex), NULL, GL_DYNAMIC_DRAW);
// Run the shader
f->glDispatchCompute(num/2, 1, 1);
f->glDispatchCompute(edgeIndices.size(), 1, 1);
// Wait for the shader to complete and the data to be written back to the global memory
f->glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
......@@ -299,19 +314,20 @@ void Subdivision::runShader(Mesh *mesh) {
// Unbind the buffers from the shader
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
// Map the output buffer so we can read the results
f->glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferID);
GLfloat *ptr;
ptr = (GLfloat *) f->glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
for (int i = 0; i < num; i++) {
qDebug()<<i<<ptr[i];
Vertex *ptr;
ptr = (Vertex *) f->glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
for (int i = 0; i < edgeIndices.size(); i++) {
qDebug() << ptr[i].pos;
}
f->glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
// Delete the buffers the free the resources
f->glDeleteBuffers(1, &offsetBufferID);
f->glDeleteBuffers(1, &indicesID);
f->glDeleteBuffers(1, &bufferID);
shader->release();
edgeShader->release();
}
......@@ -17,11 +17,11 @@ public:
private:
QOpenGLFunctions_4_3_Core *f;
QOpenGLShaderProgram *shader;
QOpenGLShaderProgram *edgeShader;
QOpenGLShaderProgram *initComputeShaderProgram();
void precomputeTables(Mesh *mesh);
void runShader(Mesh *mesh);
QOpenGLShaderProgram *initEdgeComputeShaderProgram();
void precomputeTables(Mesh *mesh, QVector<QVector<unsigned int> > &edgeIndices_base);
void runShader(Mesh *mesh, QVector<QVector<unsigned int> > &edgeIndices);
QVector<unsigned int> fillVector(unsigned int a, unsigned int b, unsigned int c,unsigned int d);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment