20 #include <CoreServices/CoreServices.h>
22 #include <OpenGL/CGLMacro.h>
24 #define glGenVertexArrays glGenVertexArraysAPPLE
25 #define glBindVertexArray glBindVertexArrayAPPLE
26 #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
35 "title" :
"VuoSceneRenderer",
44 "VuoList_VuoSceneObject",
53 typedef std::pair<std::string, double> VuoProfileEntry;
54 static bool VuoProfileSort(
const VuoProfileEntry &first,
const VuoProfileEntry &second)
56 return first.second < second.second;
86 float modelviewMatrix[16];
96 unsigned int viewportWidth;
97 unsigned int viewportHeight;
98 float backingScaleFactor;
108 list<VuoSceneRenderer_TreeRenderState> opaqueObjects;
109 list<VuoSceneRenderer_TreeRenderState> potentiallyTransparentObjects;
123 float projectionMatrix[16];
124 float cameraMatrixInverse[16];
130 float ambientBrightness;
134 GLint glContextRendererID;
146 GLenum vGL_CULL_FACE_MODE;
148 GLenum vGL_BLEND_SRC_RGB;
149 GLenum vGL_BLEND_DST_RGB;
150 GLenum vGL_BLEND_SRC_ALPHA;
151 GLenum vGL_BLEND_DST_ALPHA;
153 GLenum vGL_BLEND_EQUATION_RGB;
154 GLenum vGL_BLEND_EQUATION_ALPHA;
156 bool vGL_SAMPLE_ALPHA_TO_COVERAGE;
157 bool vGL_SAMPLE_ALPHA_TO_ONE;
162 GLuint renderDepthBuffer;
163 GLuint outputFramebuffer;
164 GLuint outputFramebuffer2;
167 std::list<VuoProfileEntry> profileTimes;
174 #define VuoSceneRenderer_setGL(cap, value) \
176 if (sceneRenderer->glState.v ## cap != value) \
182 sceneRenderer->glState.v ## cap = value; \
189 #define VuoSceneRenderer_setGLDepthMask(value) \
191 if (sceneRenderer->glState.vGL_DEPTH_MASK != value) \
193 glDepthMask(value); \
194 sceneRenderer->glState.vGL_DEPTH_MASK = value; \
201 #define VuoSceneRenderer_setGLFaceCulling(value) \
203 if (sceneRenderer->glState.vGL_CULL_FACE_MODE != value) \
206 sceneRenderer->glState.vGL_CULL_FACE_MODE = value; \
213 #define VuoSceneRenderer_setGLBlendFunction(srcRGB, dstRGB, srcAlpha, dstAlpha) \
215 if (sceneRenderer->glState.vGL_BLEND_SRC_RGB != srcRGB \
216 || sceneRenderer->glState.vGL_BLEND_DST_RGB != dstRGB \
217 || sceneRenderer->glState.vGL_BLEND_SRC_ALPHA != srcAlpha \
218 || sceneRenderer->glState.vGL_BLEND_DST_ALPHA != dstAlpha) \
220 glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); \
221 sceneRenderer->glState.vGL_BLEND_SRC_RGB = srcRGB; \
222 sceneRenderer->glState.vGL_BLEND_DST_RGB = dstRGB; \
223 sceneRenderer->glState.vGL_BLEND_SRC_ALPHA = srcAlpha; \
224 sceneRenderer->glState.vGL_BLEND_DST_ALPHA = dstAlpha; \
231 #define VuoSceneRenderer_setGLBlendEquation(modeRGB, modeAlpha) \
233 if (sceneRenderer->glState.vGL_BLEND_EQUATION_RGB != modeRGB \
234 || sceneRenderer->glState.vGL_BLEND_EQUATION_ALPHA != modeAlpha) \
236 glBlendEquationSeparate(modeRGB, modeAlpha); \
237 sceneRenderer->glState.vGL_BLEND_EQUATION_RGB = modeRGB; \
238 sceneRenderer->glState.vGL_BLEND_EQUATION_ALPHA = modeAlpha; \
247 #include "pro/VuoSceneRendererPro.h"
265 sceneRenderer->sharedTextOverrideShader = NULL;
267 sceneRenderer->cameraName = NULL;
270 sceneRenderer->backingScaleFactor = backingScaleFactor;
271 sceneRenderer->viewportWidth = 0;
272 sceneRenderer->viewportHeight = 0;
277 sceneRenderer->vignetteShader = NULL;
278 sceneRenderer->vignetteQuad =
nullptr;
280 VuoSceneRendererPro_init(sceneRenderer, cgl_ctx);
283 glGenRenderbuffersEXT(1, &sceneRenderer->renderBuffer);
284 glGenRenderbuffersEXT(1, &sceneRenderer->renderDepthBuffer);
285 glGenFramebuffers(1, &sceneRenderer->outputFramebuffer);
286 glGenFramebuffers(1, &sceneRenderer->outputFramebuffer2);
288 CGLGetParameter(cgl_ctx, kCGLCPCurrentRendererID, &sceneRenderer->glContextRendererID);
309 sceneRenderer->camera = camera;
313 if (sceneRenderer->cameraName && strlen(sceneRenderer->cameraName) != 0)
319 sceneRenderer->camera = camera;
327 sceneRenderer->camera = camera;
344 sceneRenderer->viewportWidth = width;
345 sceneRenderer->viewportHeight = height;
364 float aspectRatio = (float)sceneRenderer->viewportWidth/(
float)sceneRenderer->viewportHeight;
366 if (type == VuoSceneObjectSubType_PerspectiveCamera)
383 sceneRenderer->
projectionMatrix[10] = (cameraDistanceMax + cameraDistanceMin) / (cameraDistanceMin - cameraDistanceMax);
389 sceneRenderer->
projectionMatrix[14] = 2.f * cameraDistanceMax * cameraDistanceMin / (cameraDistanceMin - cameraDistanceMax);
392 else if (type == VuoSceneObjectSubType_StereoCamera)
396 float top = cameraDistanceMin * tanf(halfFieldOfView);
397 float right = aspectRatio * top;
399 if (!sceneRenderer->useLeftCamera)
400 frustumshift *= -1.f;
417 sceneRenderer->
projectionMatrix[10] = (cameraDistanceMax + cameraDistanceMin) / (cameraDistanceMin - cameraDistanceMax);
421 sceneRenderer->
projectionMatrix[12] = (sceneRenderer->useLeftCamera ? 1.f : -1.f) * cameraIntraocularDistance / 2.f;
423 sceneRenderer->
projectionMatrix[14] = 2.f * cameraDistanceMax * cameraDistanceMin / (cameraDistanceMin - cameraDistanceMax);
426 else if (type == VuoSceneObjectSubType_OrthographicCamera)
429 float halfWidth = cameraWidth / 2.f;
444 sceneRenderer->
projectionMatrix[10] = -2.f / (cameraDistanceMax - cameraDistanceMin);
450 sceneRenderer->
projectionMatrix[14] = -(cameraDistanceMax + cameraDistanceMin) / (cameraDistanceMax - cameraDistanceMin);
453 else if (type == VuoSceneObjectSubType_FisheyeCamera)
457 VuoSceneRendererPro_generateFisheyeProjectionMatrix(sceneRenderer, sceneRenderer->camera, aspectRatio);
467 float cameraMatrix[16];
470 float invertedCameraMatrix[16];
485 *(address++) =
'0' + i;
489 *(address++) =
'0' + (i - 10);
492 strcpy(address, suffix);
503 glGetVertexAttribiv(positionAttribute, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
506 VUserLog(
"Error: Vertex attrib array isn't enabled.");
510 unsigned int vertexCount, combinedBuffer, elementCount;
511 VuoMesh_getGPUBuffers(mesh, &vertexCount, &combinedBuffer,
nullptr,
nullptr,
nullptr, &elementCount,
nullptr);
514 glGetVertexAttribiv(positionAttribute, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &vaovbo);
515 if (vaovbo != (GLint)combinedBuffer)
516 VUserLog(
"Error: GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING (%d) doesn't match submesh's VBO (%d).", vaovbo, combinedBuffer);
518 GLint vertexBufferBound = -1;
519 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vertexBufferBound);
520 if (vertexBufferBound)
521 VUserLog(
"Error: GL_ARRAY_BUFFER_BINDING is %d (it should probably be 0, since we're using a VAO).", vertexBufferBound);
523 GLint elementBufferBound = -1;
524 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elementBufferBound);
525 if (elementCount && !elementBufferBound)
526 VUserLog(
"Error: GL_ELEMENT_ARRAY_BUFFER_BINDING is 0 (it should be nonzero, since we're trying to draw elements).");
528 GLint combinedBufferSize = -1;
529 glBindBuffer(GL_ARRAY_BUFFER, combinedBuffer);
530 glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &combinedBufferSize);
531 glBindBuffer(GL_ARRAY_BUFFER, 0);
532 if (combinedBufferSize < 4)
533 VUserLog(
"Error: combinedBuffer is unrealistically small (%d bytes).", combinedBufferSize);
535 GLint attribStride = -1;
536 glGetVertexAttribiv(positionAttribute, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attribStride);
538 GLint attribComponents = -1;
539 glGetVertexAttribiv(positionAttribute, GL_VERTEX_ATTRIB_ARRAY_SIZE, &attribComponents);
541 GLint attribType = -1;
542 glGetVertexAttribiv(positionAttribute, GL_VERTEX_ATTRIB_ARRAY_TYPE, &attribType);
544 void *attribBase = (
void *)0;
545 glGetVertexAttribPointerv(positionAttribute, GL_VERTEX_ATTRIB_ARRAY_POINTER, &attribBase);
547 unsigned int bytesPerComponent;
548 if (attribType == GL_UNSIGNED_INT)
549 bytesPerComponent = 1;
550 else if (attribType == GL_FLOAT)
551 bytesPerComponent = 4;
558 unsigned int minIndex = 0;
559 unsigned int maxIndex = 0;
563 if (elementBufferSize != elementCount *
sizeof(
unsigned int))
564 VUserLog(
"Error: elementBufferSize doesn't match elementCount.");
566 unsigned int *b = (
unsigned int *)malloc(elementBufferSize);
567 glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, elementBufferSize, b);
569 for (
unsigned int i = 0; i < elementCount; ++i)
580 maxIndex = vertexCount - 1;
582 long startWithinVBO = (long)attribBase + (
unsigned int)attribStride * minIndex;
583 long endWithinVBO = (long)attribBase +(
unsigned int) attribStride * maxIndex + (
unsigned int)attribComponents * bytesPerComponent;
585 if (startWithinVBO < 0)
587 if (endWithinVBO < 0)
589 if (startWithinVBO > endWithinVBO)
591 if (endWithinVBO > combinedBufferSize)
592 VUserLog(
"Error: end > combinedBufferSize");
624 float verticalScale = 1.;
625 float rotationZ = 0.;
634 font.pointSize *= transform.scale.x;
635 wrapWidth *= transform.scale.x;
636 verticalScale = transform.scale.y / transform.scale.x;
640 VuoPoint2d corners[4];
643 VuoPoint2d anchorOffset =
VuoSceneText_getAnchorOffset(so, verticalScale, rotationZ, wrapWidth, sceneRenderer->viewportWidth, sceneRenderer->backingScaleFactor);
644 modelviewMatrix[12] += anchorOffset.x;
645 modelviewMatrix[13] += anchorOffset.y;
655 if (isRealSize && !image)
658 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
661 GLuint timeElapsedQuery;
662 glGenQueries(1, &timeElapsedQuery);
663 glBeginQuery(GL_TIME_ELAPSED_EXT, timeElapsedQuery);
666 GLint positionAttribute = -1;
669 VDebugLog(
"Error: Couldn't fetch the 'position' attribute, needed to check data bounds.");
675 VUserLog(
"Shader activation failed.");
681 glUniformMatrix4fv(projectionMatrixUniform, 1, GL_FALSE, projectionMatrix);
684 if (useFisheyeProjectionUniform != -1)
685 glUniform1i(useFisheyeProjectionUniform,
VuoSceneObject_getType(sceneRenderer->camera) == VuoSceneObjectSubType_FisheyeCamera);
691 float billboardMatrix[16];
694 VuoPoint2d mesh0 = (VuoPoint2d){ positions[0], positions[1] };
695 VuoTransform_getBillboardMatrix(image->pixelsWide, image->pixelsHigh, image->scaleFactor,
VuoSceneObject_shouldPreservePhysicalSize(so), modelviewMatrix[12], modelviewMatrix[13], sceneRenderer->viewportWidth, sceneRenderer->viewportHeight, sceneRenderer->backingScaleFactor, mesh0, billboardMatrix);
696 glUniformMatrix4fv(modelviewMatrixUniform, 1, GL_FALSE, billboardMatrix);
699 glUniformMatrix4fv(modelviewMatrixUniform, 1, GL_FALSE, modelviewMatrix);
702 if (cameraMatrixInverseUniform != -1)
703 glUniformMatrix4fv(cameraMatrixInverseUniform, 1, GL_FALSE, sceneRenderer->
cameraMatrixInverse);
706 if (cameraPositionUniform != -1)
709 glUniform3f(cameraPositionUniform, p.x, p.y, p.z);
713 if (aspectRatioUniform != -1)
714 glUniform1f(aspectRatioUniform, (
float)sceneRenderer->viewportWidth/(
float)sceneRenderer->viewportHeight);
717 if (viewportSizeUniform != -1)
718 glUniform2f(viewportSizeUniform, (
float)sceneRenderer->viewportWidth, (
float)sceneRenderer->viewportHeight);
721 if (ambientColorUniform != -1)
724 glUniform4f(ambientColorUniform,
725 pow(sceneRenderer->ambientColor.r, 2.2) * sceneRenderer->ambientColor.a,
726 pow(sceneRenderer->ambientColor.g, 2.2) * sceneRenderer->ambientColor.a,
727 pow(sceneRenderer->ambientColor.b, 2.2) * sceneRenderer->ambientColor.a,
728 sceneRenderer->ambientColor.a);
730 if (ambientBrightnessUniform != -1)
731 glUniform1f(ambientBrightnessUniform, pow(sceneRenderer->ambientBrightness, 2.2));
733 size_t uniformSize = 27;
734 char uniformName[uniformSize];
738 if (pointLightCountUniform != -1)
740 glUniform1i(pointLightCountUniform, pointLightCount);
742 strlcpy(uniformName,
"pointLights[", uniformSize);
743 const int prefixLength = 12;
745 for (
int i=1; i<=pointLightCount; ++i)
754 glUniform4f(colorUniform,
767 glUniform3f(positionUniform, p.x, p.y, p.z);
781 if (spotLightCountUniform != -1)
783 glUniform1i(spotLightCountUniform, spotLightCount);
785 strlcpy(uniformName,
"spotLights[", uniformSize);
786 const int prefixLength = 11;
788 for (
int i=1; i<=spotLightCount; ++i)
797 glUniform4f(colorUniform,
810 glUniform3f(positionUniform, p.x, p.y, p.z);
815 glUniform3f(directionUniform, direction.x, direction.y, direction.z);
879 unsigned int vertexCount, elementCount;
880 void *textureCoordinateOffset, *colorOffset;
881 VuoMesh_getGPUBuffers(mesh, &vertexCount,
nullptr,
nullptr, &textureCoordinateOffset, &colorOffset, &elementCount,
nullptr);
884 if (hasTextureCoordinatesUniform != -1)
885 glUniform1i(hasTextureCoordinatesUniform, textureCoordinateOffset != NULL);
888 if (hasVertexColorsUniform != -1)
889 glUniform1i(hasVertexColorsUniform, colorOffset !=
nullptr);
892 if (primitiveHalfSizeUniform != -1)
896 bool enableCulling = faceCullingGL != GL_NONE && !shader->isTransparent;
909 glDrawElements(mode, completeInputElementCount, GL_UNSIGNED_INT, (
void*)0);
910 else if (vertexCount)
911 glDrawArrays(mode, 0, completeInputElementCount);
919 glEndQuery(GL_TIME_ELAPSED_EXT);
921 glGetQueryObjectuiv(timeElapsedQuery, GL_QUERY_RESULT, &nanoseconds);
922 seconds = ((double)nanoseconds) / NSEC_PER_SEC;
923 glDeleteQueries(1, &timeElapsedQuery);
925 std::string description = so.name ? std::string(so.name) :
"no name";
926 description += std::string(
" (") + shader->name +
")";
927 sceneRenderer->profileTimes.push_back(make_pair(description, seconds));
942 for (
auto currentState : renderList)
1000 VLog(
"Render lists:");
1002 for (
auto currentState : sceneRenderer->opaqueObjects)
1004 VLog(
" '%s' @ %g,%g,%g with '%s'", currentState.so->name,
1005 currentState.modelviewMatrix[12],
1006 currentState.modelviewMatrix[13],
1007 currentState.modelviewMatrix[14],
1008 currentState.so->shader ? currentState.so->shader->name : NULL
1011 VLog(
" Potentially Transparent:");
1012 for (
auto currentState : sceneRenderer->potentiallyTransparentObjects)
1014 VLog(
" '%s' @ %g,%g,%g with '%s'", currentState.so->name,
1015 currentState.modelviewMatrix[12],
1016 currentState.modelviewMatrix[13],
1017 currentState.modelviewMatrix[14],
1018 currentState.so->shader->name
1026 bzero(&sceneRenderer->glState,
sizeof(sceneRenderer->glState));
1027 sceneRenderer->glState.vGL_DEPTH_MASK =
true;
1028 sceneRenderer->glState.vGL_DEPTH_TEST =
false;
1029 sceneRenderer->glState.vGL_CULL_FACE =
true;
1030 sceneRenderer->glState.vGL_CULL_FACE_MODE = GL_BACK;
1031 sceneRenderer->glState.vGL_BLEND_SRC_RGB = GL_ONE;
1032 sceneRenderer->glState.vGL_BLEND_DST_RGB = GL_ONE_MINUS_SRC_ALPHA;
1033 sceneRenderer->glState.vGL_BLEND_SRC_ALPHA = GL_ONE;
1034 sceneRenderer->glState.vGL_BLEND_DST_ALPHA = GL_ONE_MINUS_SRC_ALPHA;
1035 sceneRenderer->glState.vGL_BLEND_EQUATION_RGB = GL_FUNC_ADD;
1036 sceneRenderer->glState.vGL_BLEND_EQUATION_ALPHA = GL_FUNC_ADD;
1037 sceneRenderer->glState.vGL_SAMPLE_ALPHA_TO_COVERAGE =
false;
1038 sceneRenderer->glState.vGL_SAMPLE_ALPHA_TO_ONE =
false;
1044 if (!sceneRenderer->potentiallyTransparentObjects.empty())
1063 VuoSceneRendererPro_drawVignette(sceneRenderer, cgl_ctx);
1068 VLog(
"Object render time (percent of a 60 Hz frame)");
1069 double totalPercent = 0;
1070 sceneRenderer->profileTimes.sort(VuoProfileSort);
1071 for (std::list<VuoProfileEntry>::iterator i = sceneRenderer->profileTimes.begin(); i != sceneRenderer->profileTimes.end(); ++i)
1073 double objectPercent = i->second / (1./60.) * 100.;
1074 VLog(
" %6.2f %s", objectPercent, i->first.c_str());
1075 totalPercent += objectPercent;
1077 VLog(
" ------ -----");
1078 VLog(
" %6.2f total", totalPercent);
1079 sceneRenderer->profileTimes.clear();
1082 glFlushRenderAPPLE();
1087 CGLGetParameter(cgl_ctx, kCGLCPCurrentRendererID, &rendererID);
1088 if (rendererID != sceneRenderer->glContextRendererID)
1091 sceneRenderer->glContextRendererID = rendererID;
1328 if (!sceneRenderer->sharedTextOverrideShader)
1331 VuoRetain(sceneRenderer->sharedTextOverrideShader);
1351 VuoSceneRendererMeshShaderVAOs::iterator i = sceneRenderer->
meshShaderItems.find(meshShader);
1354 soi->
vao = i->second;
1361 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1365 GLint positionAttribute, normalAttribute, textureCoordinateAttribute, colorAttribute;
1367 VUserLog(
"Error: Couldn't fetch the shader's attribute locations.");
1369 unsigned int combinedBuffer, elementCount, elementBuffer;
1370 void *normalOffset, *textureCoordinateOffset, *colorOffset;
1371 VuoMesh_getGPUBuffers(mesh,
nullptr, &combinedBuffer, &normalOffset, &textureCoordinateOffset, &colorOffset, &elementCount, &elementBuffer);
1382 glBindBuffer(GL_ARRAY_BUFFER, combinedBuffer);
1387 int stride =
sizeof(float) * 3;
1388 glEnableVertexAttribArray((GLuint)positionAttribute);
1389 glVertexAttribPointer((GLuint)positionAttribute, 3 , GL_FLOAT, GL_FALSE, stride, (
void*)0);
1391 if (normalOffset && normalAttribute>=0)
1393 glEnableVertexAttribArray((GLuint)normalAttribute);
1394 glVertexAttribPointer((GLuint)normalAttribute, 3 , GL_FLOAT, GL_FALSE, stride, normalOffset);
1397 if (textureCoordinateOffset && textureCoordinateAttribute>=0)
1399 glEnableVertexAttribArray((GLuint)textureCoordinateAttribute);
1400 glVertexAttribPointer((GLuint)textureCoordinateAttribute, 2 , GL_FLOAT, GL_FALSE,
sizeof(
float) * 2, textureCoordinateOffset);
1403 if (colorOffset && colorAttribute >= 0)
1405 glEnableVertexAttribArray((GLuint)colorAttribute);
1406 glVertexAttribPointer((GLuint)colorAttribute, 4 , GL_FLOAT, GL_FALSE,
sizeof(
float) * 4, colorOffset);
1411 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
1416 soi->
vao = vertexArray;
1418 glBindBuffer(GL_ARRAY_BUFFER, 0);
1440 list<VuoSceneRenderer_TreeRenderState> objects(1, rootState);
1441 while (!objects.empty())
1444 objects.pop_front();
1446 float localModelviewMatrix[16];
1448 float compositeModelviewMatrix[16];
1458 sceneRenderer->opaqueObjects.push_back(currentState);
1460 sceneRenderer->potentiallyTransparentObjects.push_back(currentState);
1463 sceneRenderer->opaqueObjects.push_back(currentState);
1472 childState.so = childObjects[i];
1474 memcpy(childState.modelviewMatrix, compositeModelviewMatrix,
sizeof(
float[16]));
1475 objects.push_front(childState);
1479 delete currentState.soi;
1506 for (
auto object : sceneRenderer->opaqueObjects)
1508 if (
object.soi->overrideShader)
1512 sceneRenderer->opaqueObjects.clear();
1514 for (
auto object : sceneRenderer->potentiallyTransparentObjects)
1516 if (
object.soi->overrideShader)
1520 sceneRenderer->potentiallyTransparentObjects.clear();
1528 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1591 if (sceneRenderer->cameraName)
1594 sceneRenderer->cameraName = cameraName;
1597 sceneRenderer->useLeftCamera = useLeftCamera;
1628 if (sceneRenderer->sharedTextOverrideShader)
1629 VuoRelease(sceneRenderer->sharedTextOverrideShader);
1631 if (sceneRenderer->cameraName)
1641 glDeleteRenderbuffersEXT(1, &sceneRenderer->renderBuffer);
1642 glDeleteRenderbuffersEXT(1, &sceneRenderer->renderDepthBuffer);
1643 glDeleteFramebuffers(1, &sceneRenderer->outputFramebuffer);
1644 glDeleteFramebuffers(1, &sceneRenderer->outputFramebuffer2);
1650 delete sceneRenderer;
1660 CGLContextObj cgl_ctx = (CGLContextObj)glContext;
1662 static bool force2DDepth =
true;
1663 static dispatch_once_t once = 0;
1664 dispatch_once(&once, ^{
1666 Boolean overridden =
false;
1667 force2DDepth = (int)CFPreferencesGetAppIntegerValue(CFSTR(
"force2DDepth"), CFSTR(
"org.vuo.Editor"), &overridden);
1677 const char *renderer = (
const char *)glGetString(GL_RENDERER);
1678 if (strcmp(renderer,
"NVIDIA GeForce GT 650M OpenGL Engine") == 0
1679 || strcmp(renderer,
"NVIDIA GeForce 9400M OpenGL Engine") == 0)
1680 force2DDepth =
false;
1682 force2DDepth =
true;
1685 VDebugLog(
"force2DDepth = %d", force2DDepth);
1689 unsigned long requiredBytes = sceneRenderer->viewportWidth * sceneRenderer->viewportHeight * colorBytesPerPixel;
1690 if (outputDepthTexture)
1691 requiredBytes += sceneRenderer->viewportWidth * sceneRenderer->viewportHeight *
VuoGlTexture_getBytesPerPixel(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT);
1695 bool actuallyMultisampling = multisample > 1;
1698 const char *renderer = (
const char *)glGetString(GL_RENDERER);
1699 if (strcmp(renderer,
"Intel HD Graphics 3000") == 0)
1704 requiredBytes += requiredBytes * multisample * fudge;
1707 if (maximumTextureBytes > 0 && requiredBytes > maximumTextureBytes)
1709 VUserLog(
"Not enough graphics memory for a %dx%d (%d bytes/pixel * %d sample) render%s. Requires %lu MB, have %lu MB.",
1710 sceneRenderer->viewportWidth, sceneRenderer->viewportHeight,
1711 colorBytesPerPixel, multisample==0?1:multisample,
1712 outputDepthTexture ?
" with depth buffer" :
"",
1713 requiredBytes/1024/1024, maximumTextureBytes/1024/1024);
1719 if (!*outputTexture)
1720 *outputTexture =
VuoGlTexturePool_use(glContext, VuoGlTexturePool_Allocate, GL_TEXTURE_2D, imageGlInternalFormat, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight, GL_BGRA, NULL);
1722 if (outputDepthTexture)
1723 *outputDepthTexture =
VuoGlTexturePool_use(glContext, VuoGlTexturePool_Allocate, GL_TEXTURE_2D, GL_DEPTH_COMPONENT, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight, GL_DEPTH_COMPONENT, NULL);
1725 if (!*outputTexture || (outputDepthTexture && !*outputDepthTexture))
1730 glBindFramebuffer(GL_FRAMEBUFFER, sceneRenderer->outputFramebuffer);
1734 if (actuallyMultisampling)
1736 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, sceneRenderer->renderBuffer);
1738 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisample, imageGlInternalFormat, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight);
1739 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER_EXT, sceneRenderer->renderBuffer);
1741 if (outputDepthTexture)
1743 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, sceneRenderer->renderDepthBuffer);
1744 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisample, GL_DEPTH_COMPONENT, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight);
1745 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, sceneRenderer->renderDepthBuffer);
1750 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, *outputTexture, 0);
1751 if (outputDepthTexture)
1752 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, force2DDepth ? GL_TEXTURE_2D : target, *outputDepthTexture, 0);
1759 if (invertDepthImage)
1763 glDepthFunc(GL_GREATER);
1769 glDepthFunc(GL_LESS);
1772 glViewport(0, 0, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight);
1773 glClearColor(0,0,0,0);
1774 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1781 if (actuallyMultisampling)
1783 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sceneRenderer->outputFramebuffer2);
1786 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, *outputTexture, 0);
1787 if (outputDepthTexture)
1788 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, force2DDepth ? GL_TEXTURE_2D : target, *outputDepthTexture, 0);
1790 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, sceneRenderer->outputFramebuffer);
1791 glReadBuffer(GL_COLOR_ATTACHMENT0);
1792 glDrawBuffer(GL_COLOR_ATTACHMENT0);
1793 glBlitFramebufferEXT(0, 0, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight,
1794 0, 0, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight,
1795 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
1798 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, 0, 0);
1799 if (outputDepthTexture)
1800 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, force2DDepth ? GL_TEXTURE_2D : target, 0, 0);
1803 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1807 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, 0, 0);
1808 if (outputDepthTexture)
1809 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, force2DDepth ? GL_TEXTURE_2D : target, 0, 0);
1813 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1817 glFlushRenderAPPLE();
1837 __block GLuint texture = 0;
1838 __block GLuint depthTexture = 0;
1840 if (!
VuoSceneRenderer_renderInternal(sr, cgl_ctx, &texture, GL_TEXTURE_2D, imageGlInternalFormat, multisample, depthImage ? &depthTexture : NULL, invertDepthImage))
1848 *image =
VuoImage_make(texture, imageGlInternalFormat, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight);
1850 *depthImage =
VuoImage_make(depthTexture, GL_DEPTH_COMPONENT, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight);
1866 __block GLuint texture = 0;
1867 __block GLuint depthTexture = 0;
1868 __block
bool renderSucceeded;
1871 vis =
VuoIoSurfacePool_use(cgl_ctx, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight, &texture);
1872 renderSucceeded =
VuoSceneRenderer_renderInternal(sr, cgl_ctx, &texture, GL_TEXTURE_RECTANGLE_ARB, imageGlInternalFormat, multisample, includeDepthBuffer ? &depthTexture : NULL,
false);
1874 if (!renderSucceeded)
1880 if (includeDepthBuffer)
1882 VuoImage depthImage =
VuoImage_make(depthTexture, GL_DEPTH_COMPONENT, sceneRenderer->viewportWidth, sceneRenderer->viewportHeight);