// // Copyright 2013 Pixar // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License // and the following modification to it: Section 6 Trademarks. // deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the // trade names, trademarks, service marks, or product names of the // Licensor and its affiliates, except as required for reproducing // the content of the NOTICE file. // // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, // either express or implied. See the License for the specific // language governing permissions and limitations under the // License. // #version 420 subroutine void computeKernelType(); subroutine uniform computeKernelType computeKernel; uniform isamplerBuffer _F0_IT; uniform isamplerBuffer _F0_ITa; uniform isamplerBuffer _E0_IT; uniform isamplerBuffer _V0_IT; uniform isamplerBuffer _V0_ITa; uniform samplerBuffer _E0_S; uniform samplerBuffer _V0_S; uniform isamplerBuffer _editIndices; uniform samplerBuffer _editValues; layout(size1x32) uniform imageBuffer _vertexBufferImage; uniform int vertexOffset = 0; // vertex index offset for the batch uniform int tableOffset = 0; // offset of subdivision table uniform int indexStart = 0; // start index relative to tableOffset uniform bool vertexPass; /* +-----+---------------------------------+----- n-1 | Level n || | n+1 +-----+---------------------------------+----- ^ ^ vertexOffset | indexStart */ //-------------------------------------------------------------------------------- struct Vertex { #if NUM_VERTEX_ELEMENTS > 0 float vertexData[NUM_VERTEX_ELEMENTS]; #endif #if NUM_VARYING_ELEMENTS > 0 float varyingData[NUM_VARYING_ELEMENTS]; #endif }; #if NUM_VERTEX_ELEMENTS > 0 uniform samplerBuffer vertexData; // float[NUM_VERTEX_ELEMENTS] #endif #if NUM_VARYING_ELEMENTS > 0 uniform samplerBuffer varyingData; // float[NUM_VARYING_ELEMENTS] #endif // output feedback (mapped as a subrange of vertices) #if NUM_VERTEX_ELEMENTS > 0 out float outVertexData[NUM_VERTEX_ELEMENTS]; #endif #if NUM_VARYING_ELEMENTS > 0 out float outVaryingData[NUM_VARYING_ELEMENTS]; #endif void clear(out Vertex v) { #if NUM_VERTEX_ELEMENTS > 0 for (int i = 0; i < NUM_VERTEX_ELEMENTS; i++) { v.vertexData[i] = 0; } #endif #if NUM_VARYING_ELEMENTS > 0 for(int i = 0; i < NUM_VARYING_ELEMENTS; i++){ v.varyingData[i] = 0; } #endif } Vertex readVertex(int index) { // XXX: should be split into two parts for addWithWeight and addVaryingWithWeight Vertex v; // unpacking #if NUM_VERTEX_ELEMENTS > 0 for(int i = 0; i < NUM_VERTEX_ELEMENTS; i++) { v.vertexData[i] = texelFetch(vertexData, index*NUM_VERTEX_ELEMENTS+i).x; } #endif #if NUM_VARYING_ELEMENTS > 0 for(int i = 0; i < NUM_VARYING_ELEMENTS; i++){ v.varyingData[i] = texelFetch(varyingData, index*NUM_VARYING_ELEMENTS+i).x; } #endif return v; } void writeVertex(Vertex v) { // packing #if NUM_VERTEX_ELEMENTS > 0 for(int i = 0; i < NUM_VERTEX_ELEMENTS; i++) { outVertexData[i] = v.vertexData[i]; } #endif #if NUM_VARYING_ELEMENTS > 0 for(int i = 0; i < NUM_VARYING_ELEMENTS; i++){ outVaryingData[i] = v.varyingData[i]; } #endif } void writeVertexByImageStore(Vertex v, int index) { #if NUM_VERTEX_ELEMENTS > 0 int p = index * NUM_VERTEX_ELEMENTS; for(int i = 0; i < NUM_VERTEX_ELEMENTS; i++) { imageStore(_vertexBufferImage, p+i, vec4(v.vertexData[i], 0, 0, 0)); } #endif } void addWithWeight(inout Vertex v, Vertex src, float weight) { #if NUM_VERTEX_ELEMENTS > 0 for(int i = 0; i < NUM_VERTEX_ELEMENTS; i++) { v.vertexData[i] += weight * src.vertexData[i]; } #endif } void addVaryingWithWeight(inout Vertex v, Vertex src, float weight) { #if NUM_VARYING_ELEMENTS > 0 for(int i = 0; i < NUM_VARYING_ELEMENTS; i++){ v.varyingData[i] += weight * src.varyingData[i]; } #endif } //-------------------------------------------------------------------------------- // Face-vertices compute Kernel subroutine(computeKernelType) void catmarkComputeFace() { int i = gl_VertexID + indexStart + tableOffset; int h = texelFetch(_F0_ITa, 2*i).x; int n = texelFetch(_F0_ITa, 2*i+1).x; float weight = 1.0/n; Vertex dst; clear(dst); for(int j=0; j0.0 && weight<1.0 && n > 0) weight=1.0-weight; Vertex dst; if(! vertexPass) clear(dst); else dst = readVertex(vid); if (eidx0==-1 || (vertexPass==false && (n==-1)) ) { addWithWeight(dst, readVertex(p), weight); } else { addWithWeight(dst, readVertex(p), weight * 0.75f); addWithWeight(dst, readVertex(eidx0), weight * 0.125f); addWithWeight(dst, readVertex(eidx1), weight * 0.125f); } if(! vertexPass) addVaryingWithWeight(dst, readVertex(p), 1); writeVertex(dst); } // Vertex-vertices compute Kernels 'B' / k_Dart and k_Smooth rules subroutine(computeKernelType) void catmarkComputeVertexB() { int i = gl_VertexID + indexStart + tableOffset; int h = texelFetch(_V0_ITa, 5*i).x; #ifdef OPT_CATMARK_V_IT_VEC2 int h2 = h/2; #endif int n = texelFetch(_V0_ITa, 5*i+1).x; int p = texelFetch(_V0_ITa, 5*i+2).x; float weight = texelFetch(_V0_S, i).x; float wp = 1.0/float(n*n); float wv = (n-2.0) * n * wp; Vertex dst; clear(dst); addWithWeight(dst, readVertex(p), weight * wv); for(int j = 0; j < n; ++j){ #ifdef OPT_CATMARK_V_IT_VEC2 ivec2 v0it = texelFetch(_V0_IT, h2+j).xy; addWithWeight(dst, readVertex(v0it.x), weight * wp); addWithWeight(dst, readVertex(v0it.y), weight * wp); #else addWithWeight(dst, readVertex(texelFetch(_V0_IT, h+j*2).x), weight * wp); addWithWeight(dst, readVertex(texelFetch(_V0_IT, h+j*2+1).x), weight * wp); #endif } addVaryingWithWeight(dst, readVertex(p), 1); writeVertex(dst); } // Vertex-vertices compute Kernels 'B' / k_Dart and k_Smooth rules subroutine(computeKernelType) void loopComputeVertexB() { float PI = 3.14159265358979323846264; int i = gl_VertexID + indexStart + tableOffset; int h = texelFetch(_V0_ITa, 5*i).x; int n = texelFetch(_V0_ITa, 5*i+1).x; int p = texelFetch(_V0_ITa, 5*i+2).x; float weight = texelFetch(_V0_S, i).x; float wp = 1.0/n; float beta = 0.25 * cos(PI*2.0f*wp)+0.375f; beta = beta * beta; beta = (0.625f-beta)*wp; Vertex dst; clear(dst); addWithWeight(dst, readVertex(p), weight * (1.0-(beta*n))); for(int j = 0; j < n; ++j){ addWithWeight(dst, readVertex(texelFetch(_V0_IT, h+j).x), weight * beta); } addVaryingWithWeight(dst, readVertex(p), 1); writeVertex(dst); } // vertex edit kernel uniform int editPrimVarOffset; uniform int editPrimVarWidth; subroutine(computeKernelType) void editAdd() { int i = gl_VertexID + indexStart + tableOffset; int v = texelFetch(_editIndices, i).x; Vertex dst = readVertex(v + vertexOffset); // this is tricky. _editValues array contains editPrimVarWidth count of values. // i.e. if the vertex edit is just for pos Y, editPrimVarOffset = 1 and // editPrimVarWidth = 1, then _editValues will be an one element array. // below loops iterate over every elements regardless editing values to be applied or not, // so we need to make out-of-range edits ineffective. #if NUM_VERTEX_ELEMENTS > 0 for (int j = 0; j < NUM_VERTEX_ELEMENTS; ++j) { int index = min(j-editPrimVarOffset, editPrimVarWidth-1); float editValue = texelFetch(_editValues, i*editPrimVarOffset + index).x; editValue *= float(j >= editPrimVarOffset); editValue *= float(j < (editPrimVarWidth + editPrimVarOffset)); dst.vertexData[j] += editValue; } #endif writeVertexByImageStore(dst, v + vertexOffset); } void main() { // call subroutine computeKernel(); }