13 #include <CoreServices/CoreServices.h>
14 #include <OpenGL/CGLMacro.h>
16 #define glGenVertexArrays glGenVertexArraysAPPLE
17 #define glBindVertexArray glBindVertexArrayAPPLE
18 #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
27 "title" :
"VuoSceneObjectRenderer",
46 GLint textureCoordinate;
49 unsigned int expectedOutputPrimitiveCount;
50 bool mayChangeOutputPrimitiveCount;
61 GLuint shamFramebuffer;
83 VUserLog(
"Error '%s' is not a transform feedback shader.", shader->
name);
93 bool havePoints =
VuoShader_getAttributeLocations(shader,
VuoMesh_Points, cgl_ctx, &sceneObjectRenderer->pointAttributes.position, &sceneObjectRenderer->pointAttributes.normal, &sceneObjectRenderer->pointAttributes.textureCoordinate, &sceneObjectRenderer->pointAttributes.color );
94 bool haveLines =
VuoShader_getAttributeLocations(shader,
VuoMesh_IndividualLines, cgl_ctx, &sceneObjectRenderer->lineAttributes.position, &sceneObjectRenderer->lineAttributes.normal, &sceneObjectRenderer->lineAttributes.textureCoordinate, &sceneObjectRenderer->lineAttributes.color );
95 bool haveTriangles =
VuoShader_getAttributeLocations(shader,
VuoMesh_IndividualTriangles, cgl_ctx, &sceneObjectRenderer->triangleAttributes.position, &sceneObjectRenderer->triangleAttributes.normal, &sceneObjectRenderer->triangleAttributes.textureCoordinate, &sceneObjectRenderer->triangleAttributes.color);
96 if (!havePoints || !haveLines || !haveTriangles)
98 VUserLog(
"Error: '%s' is missing programs for: %s %s %s", shader->
name, havePoints?
"" :
"points", haveLines?
"" :
"lines", haveTriangles?
"" :
"triangles");
99 free(sceneObjectRenderer);
100 sceneObjectRenderer = NULL;
113 sceneObjectRenderer->shader = shader;
119 sceneObjectRenderer->shamTexture =
VuoGlTexturePool_use(cgl_ctx, VuoGlTexturePool_Allocate, GL_TEXTURE_2D, GL_RGBA, 1, 1, GL_BGRA, NULL);
121 glGenFramebuffers(1, &sceneObjectRenderer->shamFramebuffer);
122 glBindFramebuffer(GL_FRAMEBUFFER, sceneObjectRenderer->shamFramebuffer);
123 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sceneObjectRenderer->shamTexture, 0);
124 glBindFramebuffer(GL_FRAMEBUFFER, 0);
126 glGenQueries(1, &sceneObjectRenderer->query);
143 GLuint outputPrimitiveGlMode;
145 int primitiveVertexMultiplier;
148 outputPrimitiveGlMode = GL_TRIANGLES;
149 attributes = sceneObjectRenderer->triangleAttributes;
150 primitiveVertexMultiplier = 3;
154 outputPrimitiveGlMode = GL_LINES;
155 attributes = sceneObjectRenderer->lineAttributes;
156 primitiveVertexMultiplier = 2;
160 outputPrimitiveGlMode = GL_POINTS;
161 attributes = sceneObjectRenderer->pointAttributes;
162 primitiveVertexMultiplier = 1;
165 unsigned int vertexCount, combinedBuffer, elementCount, elementBuffer;
166 void *normalOffset, *textureCoordinateOffset, *colorOffset;
167 VuoMesh_getGPUBuffers(mesh, &vertexCount, &combinedBuffer, &normalOffset, &textureCoordinateOffset, &colorOffset, &elementCount, &elementBuffer);
171 glBindBuffer(GL_ARRAY_BUFFER, combinedBuffer);
176 VUserLog(
"Shader activation failed.");
182 if (modelviewMatrixUniform != -1)
183 glUniformMatrix4fv(modelviewMatrixUniform, 1, GL_FALSE, modelviewMatrix);
187 if (modelviewMatrixInverseUniform != -1)
189 float modelviewMatrixInverse[16];
191 glUniformMatrix4fv(modelviewMatrixInverseUniform, 1, GL_FALSE, modelviewMatrixInverse);
195 int stride =
sizeof(float) * 3;
196 glEnableVertexAttribArray(attributes.position);
197 glVertexAttribPointer(attributes.position, 3 , GL_FLOAT, GL_FALSE, stride, (
void*)0);
198 bool hasNormals = normalOffset && attributes.normal >= 0;
201 glEnableVertexAttribArray(attributes.normal);
202 glVertexAttribPointer(attributes.normal, 3 , GL_FLOAT, GL_FALSE, stride, normalOffset);
204 bool hasTextureCoordinates = textureCoordinateOffset && attributes.textureCoordinate >= 0;
205 if (hasTextureCoordinates)
207 glEnableVertexAttribArray(attributes.textureCoordinate);
208 glVertexAttribPointer(attributes.textureCoordinate, 2 , GL_FLOAT, GL_FALSE,
sizeof(
float) * 2, textureCoordinateOffset);
210 bool hasColors = colorOffset && attributes.color >= 0;
213 glEnableVertexAttribArray(attributes.color);
214 glVertexAttribPointer(attributes.color, 4 , GL_FLOAT, GL_FALSE,
sizeof(
float) * 4, colorOffset);
220 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
226 unsigned long combinedOutputBufferSize =
sizeof(float) * (3 + 3 + 2 + 4) * outputVertexCount;
227 GLuint combinedOutputBuffer =
VuoGlPool_use(cgl_ctx, VuoGlPool_ArrayBuffer, combinedOutputBufferSize);
229 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, combinedOutputBuffer);
234 int size =
sizeof(float) * 3 * outputVertexCount;
235 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0, combinedOutputBuffer, 0, size);
237 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 1, combinedOutputBuffer, offset, size);
239 size =
sizeof(float) * 2 * outputVertexCount;
240 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 2, combinedOutputBuffer, offset, size);
242 size =
sizeof(float) * 4 * outputVertexCount;
243 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 3, combinedOutputBuffer, offset, size);
249 if (attributes.mayChangeOutputPrimitiveCount)
250 glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT, sceneObjectRenderer->query);
251 glBeginTransformFeedbackEXT(outputPrimitiveGlMode);
254 GLuint timeElapsedQuery;
255 glGenQueries(1, &timeElapsedQuery);
256 glBeginQuery(GL_TIME_ELAPSED_EXT, timeElapsedQuery);
261 glDrawElements(mode, completeInputElementCount, GL_UNSIGNED_INT, (
void*)0);
262 else if (vertexCount)
263 glDrawArrays(mode, 0, completeInputElementCount);
267 glEndQuery(GL_TIME_ELAPSED_EXT);
269 glGetQueryObjectuiv(timeElapsedQuery, GL_QUERY_RESULT, &nanoseconds);
270 seconds = ((double)nanoseconds) / NSEC_PER_SEC;
271 glDeleteQueries(1, &timeElapsedQuery);
273 double objectPercent = seconds / (1./60.) * 100.;
274 VLog(
"%6.2f %% of 60 Hz frame %s (%s)", objectPercent, sceneObject->name, sceneObjectRenderer->shader->
name);
278 glEndTransformFeedbackEXT();
279 if (attributes.mayChangeOutputPrimitiveCount)
280 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT);
282 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0);
285 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
288 glDisableVertexAttribArray(attributes.color);
289 if (hasTextureCoordinates)
290 glDisableVertexAttribArray(attributes.textureCoordinate);
292 glDisableVertexAttribArray(attributes.normal);
293 glDisableVertexAttribArray(attributes.position);
298 GLuint actualVertexCount = 0;
299 if (attributes.mayChangeOutputPrimitiveCount)
301 glGetQueryObjectuiv(sceneObjectRenderer->query, GL_QUERY_RESULT, &actualVertexCount);
302 actualVertexCount *= primitiveVertexMultiplier;
305 actualVertexCount = outputVertexCount;
310 VLog(
"inputElements=%lu actualVertexCount=%d normals=%d textureCoordinates=%d colors=%d", completeInputElementCount, actualVertexCount, hasNormals, hasTextureCoordinates, hasColors);
312 GLfloat feedback[actualVertexCount * (3 + 3 + 2 + 4)];
313 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, combinedOutputBuffer);
314 glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0,
sizeof(feedback), feedback);
315 for (
int i = 0; i < actualVertexCount; ++i)
316 fprintf(stderr,
"\t%3d = pos %5.2f %5.2f %5.2f normal %5.2f %5.2f %5.2f tc %5.2f %5.2f color %5.2f %5.2f %5.2f %5.2f\n", i,
317 feedback[i * 3], feedback[i * 3 + 1], feedback[i * 3 + 2],
318 feedback[(outputVertexCount + i) * 3], feedback[(outputVertexCount + i) * 3 + 1], feedback[(outputVertexCount + i) * 3 + 2],
319 feedback[outputVertexCount * (3 + 3) + i * 2], feedback[outputVertexCount * (3 + 3) + i * 2 + 1],
320 feedback[outputVertexCount * (3 + 3 + 2) + i * 4], feedback[outputVertexCount * (3 + 3 + 2) + i * 4 + 1], feedback[outputVertexCount * (3 + 3 + 2) + i * 4 + 2], feedback[outputVertexCount * (3 + 3 + 2) + i * 4 + 3]);
321 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0);
330 actualVertexCount, combinedOutputBuffer, combinedOutputBufferSize,
331 (
void *)(
sizeof(
float) * (3 ) * outputVertexCount),
332 (
void *)(
sizeof(
float) * (3 + 3 ) * outputVertexCount),
333 (
void *)(
sizeof(
float) * (3 + 3 + 2) * outputVertexCount),
335 outputPrimitiveMode);
343 #define ELEM(i) (elementCount ? elements[i] : i)
352 for (
int i = 0; i < verticesPerPrimitive * floatsPerVertex; ++i)
353 destination[i] = defaultValues[i % floatsPerVertex];
363 unsigned int *e = elements + start;
364 for (
int i = 0; i < verticesPerPrimitive; ++i)
365 for (
int j = 0; j < floatsPerVertex; ++j)
366 destination[i * floatsPerVertex + j] = source[*(e + i) * floatsPerVertex + j];
370 for (
int i = 0; i < verticesPerPrimitive; ++i)
371 for (
int j = 0; j < floatsPerVertex; ++j)
372 destination[i * floatsPerVertex + j] = source[(start + i) * floatsPerVertex + j];
378 if ((start / 3) % 2 == 0)
380 for (
int i = 0; i < verticesPerPrimitive; ++i)
381 for (
int j = 0; j < floatsPerVertex; ++j)
382 destination[i * floatsPerVertex + j] = source[
ELEM(start/3 + i) * floatsPerVertex + j];
386 for (
int j = 0; j < floatsPerVertex; ++j)
388 destination[0 * floatsPerVertex + j] = source[
ELEM(start/3 + 1) * floatsPerVertex + j];
389 destination[1 * floatsPerVertex + j] = source[
ELEM(start/3 ) * floatsPerVertex + j];
390 destination[2 * floatsPerVertex + j] = source[
ELEM(start/3 + 2) * floatsPerVertex + j];
397 for (
int j = 0; j < floatsPerVertex; ++j)
399 destination[0 * floatsPerVertex + j] = source[
ELEM(0 ) * floatsPerVertex + j];
400 destination[1 * floatsPerVertex + j] = source[
ELEM(start/3 + 1) * floatsPerVertex + j];
401 destination[2 * floatsPerVertex + j] = source[
ELEM(start/3 + 2) * floatsPerVertex + j];
407 for (
int j = 0; j < floatsPerVertex; ++j)
409 destination[0 * floatsPerVertex + j] = source[
ELEM(start/2 ) * floatsPerVertex + j];
410 destination[1 * floatsPerVertex + j] = source[
ELEM(start/2 + 1) * floatsPerVertex + j];
425 float *inputPositions, *inputNormals, *inputTextureCoordinates, *inputColors;
426 unsigned int elementCount, *elements;
427 VuoMesh_getCPUBuffers(mesh,
nullptr, &inputPositions, &inputNormals, &inputTextureCoordinates, &inputColors, &elementCount, &elements);
429 float modelMatrixInverse[16];
444 unsigned int allocatedVertices = inputCount;
445 float *newPositions, *newNormals, *newTextureCoordinates, *newColors;
447 unsigned int newVertexCount = 0;
449 int verticesPerPrimitive;
454 verticesPerPrimitive = 3;
457 verticesPerPrimitive = 2;
459 verticesPerPrimitive = 1;
461 float defaultPosition[3] = {0,0,0};
462 float defaultNormal[3] = {0,0,1};
463 float defaultColor[4] = {1,1,1,1};
465 for (
unsigned int e = 0; e < inputCount; e += verticesPerPrimitive)
469 allocatedVertices *= 2;
470 newPositions = (
float *)realloc(newPositions,
sizeof(
float) * 3 * allocatedVertices);
471 newNormals = (
float *)realloc(newNormals,
sizeof(
float) * 3 * allocatedVertices);
472 newTextureCoordinates = (
float *)realloc(newTextureCoordinates,
sizeof(
float) * 2 * allocatedVertices);
473 newColors = (
float *)realloc(newColors,
sizeof(
float) * 4 * allocatedVertices);
476 float *positions = newPositions + newVertexCount * 3;
477 float *normals = newNormals + newVertexCount * 3;
478 float *textureCoordinates = newTextureCoordinates + newVertexCount * 2;
479 float *colors = newColors + newVertexCount * 4;
482 VuoSceneObjectRenderer_copyElement(mesh, e, inputTextureCoordinates, elementCount, elements, elementAssemblyMethod, verticesPerPrimitive, 2, textureCoordinates, defaultPosition);
485 int vertexCount = verticesPerPrimitive;
494 cpuGeometryOperator(modelviewMatrix, modelMatrixInverse, &vertexCount, positions, normals, textureCoordinates, colors);
509 if (vertexCount % verticesPerPrimitive)
511 VUserLog(
"Error: When %d vertices are input to cpuGeometryOperator, it must output a multiple of %d vertices.", verticesPerPrimitive, verticesPerPrimitive);
515 newVertexCount += vertexCount;
523 bool originalMeshHasTextureCoordinates = inputTextureCoordinates;
524 VuoMesh newMesh =
VuoMesh_makeFromCPUBuffers(newVertexCount, newPositions, newNormals, originalMeshHasTextureCoordinates ? newTextureCoordinates :
nullptr, newColors,
526 elementAssemblyMethod);
527 if (!originalMeshHasTextureCoordinates)
528 free(newTextureCoordinates);
545 return Block_copy(^(
float *modelMatrix,
float *modelMatrixInverse,
int *vertexCount,
float *positions,
float *normals,
float *textureCoordinates,
float *colors) {
546 VuoPoint3d positionInScene[3];
547 VuoPoint3d deformedPositionInScene[3];
548 VuoPoint3d normalInScene[3];
549 VuoPoint2d textureCoordinate[3];
550 for (
int i = 0; i < *vertexCount; ++i)
568 VuoPoint3d deformedPosition = deform(positionInScene[i],
570 textureCoordinate[i]);
571 deformedPositionInScene[i] = deformedPosition;
582 VuoPoint3d tangentInScene[3], bitangentInScene[3];
583 if (*vertexCount == 3)
589 VuoPoint3d tan1[3], tan2[3];
590 bzero(tan1,
sizeof(VuoPoint3d) * 3);
591 bzero(tan2,
sizeof(VuoPoint3d) * 3);
593 VuoPoint3d v1 = positionInScene[0];
594 VuoPoint3d v2 = positionInScene[1];
595 VuoPoint3d v3 = positionInScene[2];
597 VuoPoint2d w1 = textureCoordinate[0];
598 VuoPoint2d w2 = textureCoordinate[1];
599 VuoPoint2d w3 = textureCoordinate[2];
601 float x1 = v2.x - v1.x;
602 float x2 = v3.x - v1.x;
603 float y1 = v2.y - v1.y;
604 float y2 = v3.y - v1.y;
605 float z1 = v2.z - v1.z;
606 float z2 = v3.z - v1.z;
608 float s1 = w2.x - w1.x;
609 float s2 = w3.x - w1.x;
610 float t1 = w2.y - w1.y;
611 float t2 = w3.y - w1.y;
613 float r = 1.0F / (s1 * t2 - s2 * t1);
614 VuoPoint3d sdir = (VuoPoint3d){
615 (t2 * x1 - t1 * x2) * r,
616 (t2 * y1 - t1 * y2) * r,
617 (t2 * z1 - t1 * z2) * r};
618 VuoPoint3d tdir = (VuoPoint3d){
619 (s1 * x2 - s2 * x1) * r,
620 (s1 * y2 - s2 * y1) * r,
621 (s1 * z2 - s2 * z1) * r};
631 for (
int i = 0; i < *vertexCount; ++i)
633 VuoPoint3d n = normalInScene[i];
634 VuoPoint3d t = tan1[i];
635 VuoPoint3d t2 = tan2[i];
643 for (
int i = 0; i < *vertexCount; ++i)
645 tangentInScene[i] = (VuoPoint3d){1,0,0};
646 bitangentInScene[i] = (VuoPoint3d){0,1,0};
652 for (
int i = 0; i < *vertexCount; ++i)
654 const float scale = .01;
655 VuoPoint3d deformedAlongTangent = deform(positionInScene[i] + tangentInScene[i] * scale,
657 textureCoordinate[i] + (VuoPoint2d){scale, 0});
658 VuoPoint3d deformedAlongBitangent = deform(positionInScene[i] + bitangentInScene[i] * scale,
660 textureCoordinate[i] + (VuoPoint2d){0, scale});
662 VuoPoint3d deformedPosition = deformedPositionInScene[i];
665 VuoPoint3d deformedTangent = deformedAlongTangent - deformedPosition;
666 VuoPoint3d deformedBitangent = deformedAlongBitangent - deformedPosition;
684 static bool gpuTransformFeedback;
685 static dispatch_once_t once = 0;
686 dispatch_once(&once, ^{
688 Boolean overridden =
false;
689 gpuTransformFeedback = (int)CFPreferencesGetAppIntegerValue(CFSTR(
"gpuTransformFeedback"), CFSTR(
"org.vuo.Editor"), &overridden);
696 __block
const char *renderer;
698 renderer = (
const char *)glGetString(GL_RENDERER);
701 if (strncmp(renderer,
"Intel", 5) == 0
702 || strncmp(renderer,
"AMD ", 4) == 0
703 || strncmp(renderer,
"NVIDIA GeForce 9400M", 4) == 0
704 || strncmp(renderer,
"ATI ", 4) == 0)
705 gpuTransformFeedback =
false;
708 gpuTransformFeedback =
true;
711 VDebugLog(
"gpuTransformFeedback = %d", gpuTransformFeedback);
714 return gpuTransformFeedback;
744 glEnable(GL_RASTERIZER_DISCARD_EXT);
746 glBindFramebuffer(GL_FRAMEBUFFER, sceneObjectRenderer->shamFramebuffer);
752 glBindBuffer(GL_ARRAY_BUFFER, 0);
753 glBindFramebuffer(GL_FRAMEBUFFER, 0);
755 glDisable(GL_RASTERIZER_DISCARD_EXT);
759 glFlushRenderAPPLE();
762 return sceneObjectCopy;
773 return sceneObjectCopy;
790 glBindFramebuffer(GL_FRAMEBUFFER, sceneObjectRenderer->shamFramebuffer);
791 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
792 VuoGlTexture_release(VuoGlTexturePool_Allocate, GL_TEXTURE_2D, GL_RGBA, 1, 1, sceneObjectRenderer->shamTexture);
794 glDeleteFramebuffers(1, &sceneObjectRenderer->shamFramebuffer);
798 glDeleteQueries(1, &sceneObjectRenderer->query);
801 free(sceneObjectRenderer);