81 VUserLog(
"Error '%s' is not a transform feedback shader.", shader->name);
91 bool havePoints =
VuoShader_getAttributeLocations(shader,
VuoMesh_Points, cgl_ctx, &sceneObjectRenderer->pointAttributes.position, &sceneObjectRenderer->pointAttributes.normal, &sceneObjectRenderer->pointAttributes.textureCoordinate, &sceneObjectRenderer->pointAttributes.color );
92 bool haveLines =
VuoShader_getAttributeLocations(shader,
VuoMesh_IndividualLines, cgl_ctx, &sceneObjectRenderer->lineAttributes.position, &sceneObjectRenderer->lineAttributes.normal, &sceneObjectRenderer->lineAttributes.textureCoordinate, &sceneObjectRenderer->lineAttributes.color );
93 bool haveTriangles =
VuoShader_getAttributeLocations(shader,
VuoMesh_IndividualTriangles, cgl_ctx, &sceneObjectRenderer->triangleAttributes.position, &sceneObjectRenderer->triangleAttributes.normal, &sceneObjectRenderer->triangleAttributes.textureCoordinate, &sceneObjectRenderer->triangleAttributes.color);
94 if (!havePoints || !haveLines || !haveTriangles)
96 VUserLog(
"Error: '%s' is missing programs for: %s %s %s", shader->name, havePoints?
"" :
"points", haveLines?
"" :
"lines", haveTriangles?
"" :
"triangles");
97 free(sceneObjectRenderer);
98 sceneObjectRenderer = NULL;
111 sceneObjectRenderer->shader = shader;
117 sceneObjectRenderer->shamTexture =
VuoGlTexturePool_use(cgl_ctx, VuoGlTexturePool_Allocate, GL_TEXTURE_2D, GL_RGBA, 1, 1, GL_BGRA, NULL);
119 glGenFramebuffers(1, &sceneObjectRenderer->shamFramebuffer);
120 glBindFramebuffer(GL_FRAMEBUFFER, sceneObjectRenderer->shamFramebuffer);
121 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sceneObjectRenderer->shamTexture, 0);
122 glBindFramebuffer(GL_FRAMEBUFFER, 0);
124 glGenQueries(1, &sceneObjectRenderer->query);
141 GLuint outputPrimitiveGlMode;
143 int primitiveVertexMultiplier;
146 outputPrimitiveGlMode = GL_TRIANGLES;
147 attributes = sceneObjectRenderer->triangleAttributes;
148 primitiveVertexMultiplier = 3;
152 outputPrimitiveGlMode = GL_LINES;
153 attributes = sceneObjectRenderer->lineAttributes;
154 primitiveVertexMultiplier = 2;
158 outputPrimitiveGlMode = GL_POINTS;
159 attributes = sceneObjectRenderer->pointAttributes;
160 primitiveVertexMultiplier = 1;
163 unsigned int vertexCount, combinedBuffer, elementCount, elementBuffer;
164 void *normalOffset, *textureCoordinateOffset, *colorOffset;
165 VuoMesh_getGPUBuffers(mesh, &vertexCount, &combinedBuffer, &normalOffset, &textureCoordinateOffset, &colorOffset, &elementCount, &elementBuffer);
169 glBindBuffer(GL_ARRAY_BUFFER, combinedBuffer);
174 VUserLog(
"Shader activation failed.");
180 if (modelviewMatrixUniform != -1)
181 glUniformMatrix4fv(modelviewMatrixUniform, 1, GL_FALSE, modelviewMatrix);
185 if (modelviewMatrixInverseUniform != -1)
187 float modelviewMatrixInverse[16];
189 glUniformMatrix4fv(modelviewMatrixInverseUniform, 1, GL_FALSE, modelviewMatrixInverse);
193 int stride =
sizeof(float) * 3;
194 glEnableVertexAttribArray(attributes.position);
195 glVertexAttribPointer(attributes.position, 3 , GL_FLOAT, GL_FALSE, stride, (
void*)0);
196 bool hasNormals = normalOffset && attributes.normal >= 0;
199 glEnableVertexAttribArray(attributes.normal);
200 glVertexAttribPointer(attributes.normal, 3 , GL_FLOAT, GL_FALSE, stride, normalOffset);
202 bool hasTextureCoordinates = textureCoordinateOffset && attributes.textureCoordinate >= 0;
203 if (hasTextureCoordinates)
205 glEnableVertexAttribArray(attributes.textureCoordinate);
206 glVertexAttribPointer(attributes.textureCoordinate, 2 , GL_FLOAT, GL_FALSE,
sizeof(
float) * 2, textureCoordinateOffset);
208 bool hasColors = colorOffset && attributes.color >= 0;
211 glEnableVertexAttribArray(attributes.color);
212 glVertexAttribPointer(attributes.color, 4 , GL_FLOAT, GL_FALSE,
sizeof(
float) * 4, colorOffset);
218 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
224 unsigned long combinedOutputBufferSize =
sizeof(float) * (3 + 3 + 2 + 4) * outputVertexCount;
225 GLuint combinedOutputBuffer =
VuoGlPool_use(cgl_ctx, VuoGlPool_ArrayBuffer, combinedOutputBufferSize);
227 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, combinedOutputBuffer);
232 int size =
sizeof(float) * 3 * outputVertexCount;
233 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0, combinedOutputBuffer, 0, size);
235 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 1, combinedOutputBuffer, offset, size);
237 size =
sizeof(float) * 2 * outputVertexCount;
238 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 2, combinedOutputBuffer, offset, size);
240 size =
sizeof(float) * 4 * outputVertexCount;
241 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 3, combinedOutputBuffer, offset, size);
247 if (attributes.mayChangeOutputPrimitiveCount)
248 glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT, sceneObjectRenderer->query);
249 glBeginTransformFeedbackEXT(outputPrimitiveGlMode);
252 GLuint timeElapsedQuery;
253 glGenQueries(1, &timeElapsedQuery);
254 glBeginQuery(GL_TIME_ELAPSED_EXT, timeElapsedQuery);
259 glDrawElements(mode, completeInputElementCount, GL_UNSIGNED_INT, (
void*)0);
260 else if (vertexCount)
261 glDrawArrays(mode, 0, completeInputElementCount);
265 glEndQuery(GL_TIME_ELAPSED_EXT);
267 glGetQueryObjectuiv(timeElapsedQuery, GL_QUERY_RESULT, &nanoseconds);
268 seconds = ((double)nanoseconds) / NSEC_PER_SEC;
269 glDeleteQueries(1, &timeElapsedQuery);
271 double objectPercent = seconds / (1./60.) * 100.;
272 VLog(
"%6.2f %% of 60 Hz frame %s (%s)", objectPercent, sceneObject->name, sceneObjectRenderer->shader->name);
276 glEndTransformFeedbackEXT();
277 if (attributes.mayChangeOutputPrimitiveCount)
278 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT);
280 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0);
283 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
286 glDisableVertexAttribArray(attributes.color);
287 if (hasTextureCoordinates)
288 glDisableVertexAttribArray(attributes.textureCoordinate);
290 glDisableVertexAttribArray(attributes.normal);
291 glDisableVertexAttribArray(attributes.position);
296 GLuint actualVertexCount = 0;
297 if (attributes.mayChangeOutputPrimitiveCount)
299 glGetQueryObjectuiv(sceneObjectRenderer->query, GL_QUERY_RESULT, &actualVertexCount);
300 actualVertexCount *= primitiveVertexMultiplier;
303 actualVertexCount = outputVertexCount;
308 VLog(
"inputElements=%lu actualVertexCount=%d normals=%d textureCoordinates=%d colors=%d", completeInputElementCount, actualVertexCount, hasNormals, hasTextureCoordinates, hasColors);
310 GLfloat feedback[actualVertexCount * (3 + 3 + 2 + 4)];
311 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, combinedOutputBuffer);
312 glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0,
sizeof(feedback), feedback);
313 for (
int i = 0; i < actualVertexCount; ++i)
314 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,
315 feedback[i * 3], feedback[i * 3 + 1], feedback[i * 3 + 2],
316 feedback[(outputVertexCount + i) * 3], feedback[(outputVertexCount + i) * 3 + 1], feedback[(outputVertexCount + i) * 3 + 2],
317 feedback[outputVertexCount * (3 + 3) + i * 2], feedback[outputVertexCount * (3 + 3) + i * 2 + 1],
318 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]);
319 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0);
335 actualVertexCount, combinedOutputBuffer, combinedOutputBufferSize,
336 (
void *)(
sizeof(
float) * (3 ) * outputVertexCount),
337 hasTextureCoordinates ? (
void *)(
sizeof(
float) * (3 + 3 ) * outputVertexCount) :
nullptr,
338 hasColors ? (
void *)(
sizeof(
float) * (3 + 3 + 2) * outputVertexCount) :
nullptr,
340 outputPrimitiveMode);
357 for (
int i = 0; i < verticesPerPrimitive * floatsPerVertex; ++i)
358 destination[i] = defaultValues[i % floatsPerVertex];
368 unsigned int *e = elements + start;
369 for (
int i = 0; i < verticesPerPrimitive; ++i)
370 for (
int j = 0; j < floatsPerVertex; ++j)
371 destination[i * floatsPerVertex + j] = source[*(e + i) * floatsPerVertex + j];
375 for (
int i = 0; i < verticesPerPrimitive; ++i)
376 for (
int j = 0; j < floatsPerVertex; ++j)
377 destination[i * floatsPerVertex + j] = source[(start + i) * floatsPerVertex + j];
383 if ((start / 3) % 2 == 0)
385 for (
int i = 0; i < verticesPerPrimitive; ++i)
386 for (
int j = 0; j < floatsPerVertex; ++j)
387 destination[i * floatsPerVertex + j] = source[
ELEM(start/3 + i) * floatsPerVertex + j];
391 for (
int j = 0; j < floatsPerVertex; ++j)
393 destination[0 * floatsPerVertex + j] = source[
ELEM(start/3 + 1) * floatsPerVertex + j];
394 destination[1 * floatsPerVertex + j] = source[
ELEM(start/3 ) * floatsPerVertex + j];
395 destination[2 * floatsPerVertex + j] = source[
ELEM(start/3 + 2) * floatsPerVertex + j];
402 for (
int j = 0; j < floatsPerVertex; ++j)
404 destination[0 * floatsPerVertex + j] = source[
ELEM(0 ) * floatsPerVertex + j];
405 destination[1 * floatsPerVertex + j] = source[
ELEM(start/3 + 1) * floatsPerVertex + j];
406 destination[2 * floatsPerVertex + j] = source[
ELEM(start/3 + 2) * floatsPerVertex + j];
412 for (
int j = 0; j < floatsPerVertex; ++j)
414 destination[0 * floatsPerVertex + j] = source[
ELEM(start/2 ) * floatsPerVertex + j];
415 destination[1 * floatsPerVertex + j] = source[
ELEM(start/2 + 1) * floatsPerVertex + j];
430 float *inputPositions, *inputNormals, *inputTextureCoordinates, *inputColors;
431 unsigned int elementCount, *elements;
432 VuoMesh_getCPUBuffers(mesh,
nullptr, &inputPositions, &inputNormals, &inputTextureCoordinates, &inputColors, &elementCount, &elements);
434 float modelMatrixInverse[16];
449 unsigned int allocatedVertices = inputCount;
450 float *newPositions, *newNormals, *newTextureCoordinates, *newColors;
452 unsigned int newVertexCount = 0;
454 int verticesPerPrimitive;
459 verticesPerPrimitive = 3;
462 verticesPerPrimitive = 2;
464 verticesPerPrimitive = 1;
466 float defaultPosition[3] = {0,0,0};
467 float defaultNormal[3] = {0,0,1};
468 float defaultColor[4] = {1,1,1,1};
470 for (
unsigned int e = 0; e < inputCount; e += verticesPerPrimitive)
474 allocatedVertices *= 2;
475 newPositions = (
float *)realloc(newPositions,
sizeof(
float) * 3 * allocatedVertices);
476 newNormals = (
float *)realloc(newNormals,
sizeof(
float) * 3 * allocatedVertices);
477 newTextureCoordinates = (
float *)realloc(newTextureCoordinates,
sizeof(
float) * 2 * allocatedVertices);
478 newColors = (
float *)realloc(newColors,
sizeof(
float) * 4 * allocatedVertices);
481 float *positions = newPositions + newVertexCount * 3;
482 float *normals = newNormals + newVertexCount * 3;
483 float *textureCoordinates = newTextureCoordinates + newVertexCount * 2;
484 float *colors = newColors + newVertexCount * 4;
487 VuoSceneObjectRenderer_copyElement(mesh, e, inputTextureCoordinates, elementCount, elements, elementAssemblyMethod, verticesPerPrimitive, 2, textureCoordinates, defaultPosition);
490 int vertexCount = verticesPerPrimitive;
499 cpuGeometryOperator(modelviewMatrix, modelMatrixInverse, &vertexCount, positions, normals, textureCoordinates, colors);
514 if (vertexCount % verticesPerPrimitive)
516 VUserLog(
"Error: When %d vertices are input to cpuGeometryOperator, it must output a multiple of %d vertices.", verticesPerPrimitive, verticesPerPrimitive);
520 newVertexCount += vertexCount;
528 bool originalMeshHasTextureCoordinates = inputTextureCoordinates;
529 VuoMesh newMesh =
VuoMesh_makeFromCPUBuffers(newVertexCount, newPositions, newNormals, originalMeshHasTextureCoordinates ? newTextureCoordinates :
nullptr, newColors,
531 elementAssemblyMethod);
532 if (!originalMeshHasTextureCoordinates)
533 free(newTextureCoordinates);
550 return Block_copy(^(
float *modelMatrix,
float *modelMatrixInverse,
int *vertexCount,
float *positions,
float *normals,
float *textureCoordinates,
float *colors) {
551 VuoPoint3d positionInScene[3];
552 VuoPoint3d deformedPositionInScene[3];
553 VuoPoint3d normalInScene[3];
554 VuoPoint2d textureCoordinate[3];
555 for (
int i = 0; i < *vertexCount; ++i)
573 VuoPoint3d deformedPosition = deform(positionInScene[i],
575 textureCoordinate[i]);
576 deformedPositionInScene[i] = deformedPosition;
587 VuoPoint3d tangentInScene[3], bitangentInScene[3];
588 if (*vertexCount == 3)
594 VuoPoint3d tan1[3], tan2[3];
595 bzero(tan1,
sizeof(VuoPoint3d) * 3);
596 bzero(tan2,
sizeof(VuoPoint3d) * 3);
598 VuoPoint3d v1 = positionInScene[0];
599 VuoPoint3d v2 = positionInScene[1];
600 VuoPoint3d v3 = positionInScene[2];
602 VuoPoint2d w1 = textureCoordinate[0];
603 VuoPoint2d w2 = textureCoordinate[1];
604 VuoPoint2d w3 = textureCoordinate[2];
606 float x1 = v2.x - v1.x;
607 float x2 = v3.x - v1.x;
608 float y1 = v2.y - v1.y;
609 float y2 = v3.y - v1.y;
610 float z1 = v2.z - v1.z;
611 float z2 = v3.z - v1.z;
613 float s1 = w2.x - w1.x;
614 float s2 = w3.x - w1.x;
615 float t1 = w2.y - w1.y;
616 float t2 = w3.y - w1.y;
618 float r = 1.0F / (s1 * t2 - s2 * t1);
619 VuoPoint3d sdir = (VuoPoint3d){
620 (t2 * x1 - t1 * x2) * r,
621 (t2 * y1 - t1 * y2) * r,
622 (t2 * z1 - t1 * z2) * r};
623 VuoPoint3d tdir = (VuoPoint3d){
624 (s1 * x2 - s2 * x1) * r,
625 (s1 * y2 - s2 * y1) * r,
626 (s1 * z2 - s2 * z1) * r};
636 for (
int i = 0; i < *vertexCount; ++i)
638 VuoPoint3d n = normalInScene[i];
639 VuoPoint3d t = tan1[i];
640 VuoPoint3d t2 = tan2[i];
648 for (
int i = 0; i < *vertexCount; ++i)
650 tangentInScene[i] = (VuoPoint3d){1,0,0};
651 bitangentInScene[i] = (VuoPoint3d){0,1,0};
657 for (
int i = 0; i < *vertexCount; ++i)
659 const float scale = .01;
660 VuoPoint3d deformedAlongTangent = deform(positionInScene[i] + tangentInScene[i] * scale,
662 textureCoordinate[i] + (VuoPoint2d){scale, 0});
663 VuoPoint3d deformedAlongBitangent = deform(positionInScene[i] + bitangentInScene[i] * scale,
665 textureCoordinate[i] + (VuoPoint2d){0, scale});
667 VuoPoint3d deformedPosition = deformedPositionInScene[i];
670 VuoPoint3d deformedTangent = deformedAlongTangent - deformedPosition;
671 VuoPoint3d deformedBitangent = deformedAlongBitangent - deformedPosition;